diff --git a/compiled_starters/elixir/.codecrafters/compile.sh b/compiled_starters/elixir/.codecrafters/compile.sh new file mode 100755 index 0000000..806dc02 --- /dev/null +++ b/compiled_starters/elixir/.codecrafters/compile.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +mix escript.build +mv codecrafters_git /tmp/codecrafters-build-git-elixir diff --git a/compiled_starters/elixir/.codecrafters/run.sh b/compiled_starters/elixir/.codecrafters/run.sh new file mode 100755 index 0000000..accb20c --- /dev/null +++ b/compiled_starters/elixir/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec /tmp/codecrafters-build-git-elixir "$@" diff --git a/compiled_starters/elixir/.formatter.exs b/compiled_starters/elixir/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/compiled_starters/elixir/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/compiled_starters/elixir/.gitattributes b/compiled_starters/elixir/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/compiled_starters/elixir/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/compiled_starters/elixir/.gitignore b/compiled_starters/elixir/.gitignore new file mode 100644 index 0000000..881ad01 --- /dev/null +++ b/compiled_starters/elixir/.gitignore @@ -0,0 +1,27 @@ +# Ignore the compiled binary +/codecrafters_git + +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +app-*.tar + diff --git a/compiled_starters/elixir/README.md b/compiled_starters/elixir/README.md new file mode 100644 index 0000000..68fd14e --- /dev/null +++ b/compiled_starters/elixir/README.md @@ -0,0 +1,59 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/git.png) + +This is a starting point for Elixir solutions to the +["Build Your Own Git" Challenge](https://codecrafters.io/challenges/git). + +In this challenge, you'll build a small Git implementation that's capable of +initializing a repository, creating commits and cloning a public repository. +Along the way we'll learn about the `.git` directory, Git objects (blobs, +commits, trees etc.), Git's transfer protocols and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Git implementation is in `lib/main.ex`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `mix` installed locally +1. Run `./your_program.sh` to run your Git implementation, which is implemented + in `lib/main.ex`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. + +# Testing locally + +The `your_program.sh` script is expected to operate on the `.git` folder inside +the current working directory. If you're running this inside the root of this +repository, you might end up accidentally damaging your repository's `.git` +folder. + +We suggest executing `your_program.sh` in a different folder when testing +locally. For example: + +```sh +mkdir -p /tmp/testing && cd /tmp/testing +/path/to/your/repo/your_program.sh init +``` + +To make this easier to type out, you could add a +[shell alias](https://shapeshed.com/unix-alias/): + +```sh +alias mygit=/path/to/your/repo/your_program.sh + +mkdir -p /tmp/testing && cd /tmp/testing +mygit init +``` diff --git a/compiled_starters/elixir/codecrafters.yml b/compiled_starters/elixir/codecrafters.yml new file mode 100644 index 0000000..eaed767 --- /dev/null +++ b/compiled_starters/elixir/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the Elixir version used to run your code +# on Codecrafters. +# +# Available versions: elixir-1.17 +language_pack: elixir-1.17 diff --git a/compiled_starters/elixir/lib/main.ex b/compiled_starters/elixir/lib/main.ex new file mode 100644 index 0000000..b3be542 --- /dev/null +++ b/compiled_starters/elixir/lib/main.ex @@ -0,0 +1,25 @@ +defmodule CLI do + def main(argv) do + # You can use print statements as follows for debugging, they'll be visible when running tests. + IO.puts("Logs from your program will appear here!") + + # Uncomment this block to pass the first stage + # + # case argv do + # ["init" | _] -> + # :ok = File.mkdir(".git") + # :ok = File.mkdir(".git/objects") + # :ok = File.mkdir(".git/refs") + # :ok = File.write(".git/HEAD", "ref: refs/heads/main\n") + # IO.puts("Initialized git directory") + # + # [command | _] -> + # IO.puts("Unknown command: #{command}") + # System.halt(1) + # + # [] -> + # IO.puts("Usage: your_script.sh ") + # System.halt(1) + # end + end +end diff --git a/compiled_starters/elixir/mix.exs b/compiled_starters/elixir/mix.exs new file mode 100644 index 0000000..65acad0 --- /dev/null +++ b/compiled_starters/elixir/mix.exs @@ -0,0 +1,30 @@ +defmodule App.MixProject do + # NOTE: You do not need to change anything in this file. + use Mix.Project + + def project do + [ + app: :codecrafters_git, + version: "1.0.0", + elixir: "~> 1.17", + start_permanent: Mix.env() == :prod, + deps: deps(), + escript: [main_module: CLI] + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/compiled_starters/elixir/your_program.sh b/compiled_starters/elixir/your_program.sh new file mode 100755 index 0000000..000993a --- /dev/null +++ b/compiled_starters/elixir/your_program.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + mix escript.build + mv codecrafters_git /tmp/codecrafters-build-git-elixir +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec /tmp/codecrafters-build-git-elixir "$@" diff --git a/dockerfiles/elixir-1.17.Dockerfile b/dockerfiles/elixir-1.17.Dockerfile new file mode 100644 index 0000000..e424f78 --- /dev/null +++ b/dockerfiles/elixir-1.17.Dockerfile @@ -0,0 +1,17 @@ +# syntax=docker/dockerfile:1.7-labs +FROM elixir:1.17.2-alpine + +# Ensures the container is re-built if dependency files change +ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="mix.exs" + +WORKDIR /app + +# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses +COPY --exclude=.git --exclude=README.md . /app + +# Install & cache deps +RUN .codecrafters/compile.sh + +# If _build directory exists, move it to /app-cached +RUN mkdir -p /app-cached +RUN if [ -d "/app/_build" ]; then mv /app/_build /app-cached; fi diff --git a/solutions/elixir/01-gg4/code/.codecrafters/compile.sh b/solutions/elixir/01-gg4/code/.codecrafters/compile.sh new file mode 100755 index 0000000..806dc02 --- /dev/null +++ b/solutions/elixir/01-gg4/code/.codecrafters/compile.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +mix escript.build +mv codecrafters_git /tmp/codecrafters-build-git-elixir diff --git a/solutions/elixir/01-gg4/code/.codecrafters/run.sh b/solutions/elixir/01-gg4/code/.codecrafters/run.sh new file mode 100755 index 0000000..accb20c --- /dev/null +++ b/solutions/elixir/01-gg4/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec /tmp/codecrafters-build-git-elixir "$@" diff --git a/solutions/elixir/01-gg4/code/.formatter.exs b/solutions/elixir/01-gg4/code/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/solutions/elixir/01-gg4/code/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/solutions/elixir/01-gg4/code/.gitattributes b/solutions/elixir/01-gg4/code/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/solutions/elixir/01-gg4/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/elixir/01-gg4/code/.gitignore b/solutions/elixir/01-gg4/code/.gitignore new file mode 100644 index 0000000..881ad01 --- /dev/null +++ b/solutions/elixir/01-gg4/code/.gitignore @@ -0,0 +1,27 @@ +# Ignore the compiled binary +/codecrafters_git + +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +app-*.tar + diff --git a/solutions/elixir/01-gg4/code/README.md b/solutions/elixir/01-gg4/code/README.md new file mode 100644 index 0000000..68fd14e --- /dev/null +++ b/solutions/elixir/01-gg4/code/README.md @@ -0,0 +1,59 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/git.png) + +This is a starting point for Elixir solutions to the +["Build Your Own Git" Challenge](https://codecrafters.io/challenges/git). + +In this challenge, you'll build a small Git implementation that's capable of +initializing a repository, creating commits and cloning a public repository. +Along the way we'll learn about the `.git` directory, Git objects (blobs, +commits, trees etc.), Git's transfer protocols and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your Git implementation is in `lib/main.ex`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git commit -am "pass 1st stage" # any msg +git push origin master +``` + +That's all! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `mix` installed locally +1. Run `./your_program.sh` to run your Git implementation, which is implemented + in `lib/main.ex`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. + +# Testing locally + +The `your_program.sh` script is expected to operate on the `.git` folder inside +the current working directory. If you're running this inside the root of this +repository, you might end up accidentally damaging your repository's `.git` +folder. + +We suggest executing `your_program.sh` in a different folder when testing +locally. For example: + +```sh +mkdir -p /tmp/testing && cd /tmp/testing +/path/to/your/repo/your_program.sh init +``` + +To make this easier to type out, you could add a +[shell alias](https://shapeshed.com/unix-alias/): + +```sh +alias mygit=/path/to/your/repo/your_program.sh + +mkdir -p /tmp/testing && cd /tmp/testing +mygit init +``` diff --git a/solutions/elixir/01-gg4/code/codecrafters.yml b/solutions/elixir/01-gg4/code/codecrafters.yml new file mode 100644 index 0000000..eaed767 --- /dev/null +++ b/solutions/elixir/01-gg4/code/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the Elixir version used to run your code +# on Codecrafters. +# +# Available versions: elixir-1.17 +language_pack: elixir-1.17 diff --git a/solutions/elixir/01-gg4/code/lib/main.ex b/solutions/elixir/01-gg4/code/lib/main.ex new file mode 100644 index 0000000..67bf0e9 --- /dev/null +++ b/solutions/elixir/01-gg4/code/lib/main.ex @@ -0,0 +1,20 @@ +defmodule CLI do + def main(argv) do + case argv do + ["init" | _] -> + :ok = File.mkdir(".git") + :ok = File.mkdir(".git/objects") + :ok = File.mkdir(".git/refs") + :ok = File.write(".git/HEAD", "ref: refs/heads/main\n") + IO.puts("Initialized git directory") + + [command | _] -> + IO.puts("Unknown command: #{command}") + System.halt(1) + + [] -> + IO.puts("Usage: your_script.sh ") + System.halt(1) + end + end +end diff --git a/solutions/elixir/01-gg4/code/mix.exs b/solutions/elixir/01-gg4/code/mix.exs new file mode 100644 index 0000000..65acad0 --- /dev/null +++ b/solutions/elixir/01-gg4/code/mix.exs @@ -0,0 +1,30 @@ +defmodule App.MixProject do + # NOTE: You do not need to change anything in this file. + use Mix.Project + + def project do + [ + app: :codecrafters_git, + version: "1.0.0", + elixir: "~> 1.17", + start_permanent: Mix.env() == :prod, + deps: deps(), + escript: [main_module: CLI] + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/solutions/elixir/01-gg4/code/your_program.sh b/solutions/elixir/01-gg4/code/your_program.sh new file mode 100755 index 0000000..000993a --- /dev/null +++ b/solutions/elixir/01-gg4/code/your_program.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + mix escript.build + mv codecrafters_git /tmp/codecrafters-build-git-elixir +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec /tmp/codecrafters-build-git-elixir "$@" diff --git a/solutions/elixir/01-gg4/diff/lib/main.ex.diff b/solutions/elixir/01-gg4/diff/lib/main.ex.diff new file mode 100644 index 0000000..bfa6f2d --- /dev/null +++ b/solutions/elixir/01-gg4/diff/lib/main.ex.diff @@ -0,0 +1,41 @@ +@@ -1,25 +1,20 @@ + defmodule CLI do + def main(argv) do +- # You can use print statements as follows for debugging, they'll be visible when running tests. +- IO.puts("Logs from your program will appear here!") ++ case argv do ++ ["init" | _] -> ++ :ok = File.mkdir(".git") ++ :ok = File.mkdir(".git/objects") ++ :ok = File.mkdir(".git/refs") ++ :ok = File.write(".git/HEAD", "ref: refs/heads/main\n") ++ IO.puts("Initialized git directory") + +- # Uncomment this block to pass the first stage +- # +- # case argv do +- # ["init" | _] -> +- # :ok = File.mkdir(".git") +- # :ok = File.mkdir(".git/objects") +- # :ok = File.mkdir(".git/refs") +- # :ok = File.write(".git/HEAD", "ref: refs/heads/main\n") +- # IO.puts("Initialized git directory") +- # +- # [command | _] -> +- # IO.puts("Unknown command: #{command}") +- # System.halt(1) +- # +- # [] -> +- # IO.puts("Usage: your_script.sh ") +- # System.halt(1) +- # end ++ [command | _] -> ++ IO.puts("Unknown command: #{command}") ++ System.halt(1) ++ ++ [] -> ++ IO.puts("Usage: your_script.sh ") ++ System.halt(1) ++ end + end + end diff --git a/solutions/elixir/01-gg4/explanation.md b/solutions/elixir/01-gg4/explanation.md new file mode 100644 index 0000000..74d49ac --- /dev/null +++ b/solutions/elixir/01-gg4/explanation.md @@ -0,0 +1,32 @@ +The entry point for your Git implementation is in `lib/main.ex`. + +Study and uncomment the relevant code: + +```elixir +# Uncomment this block to pass the first stage + +case argv do + ["init" | _] -> + :ok = File.mkdir(".git") + :ok = File.mkdir(".git/objects") + :ok = File.mkdir(".git/refs") + :ok = File.write(".git/HEAD", "ref: refs/heads/main\n") + IO.puts("Initialized git directory") + + [command | _] -> + IO.puts("Unknown command: #{command}") + System.halt(1) + + [] -> + IO.puts("Usage: your_script.sh ") + System.halt(1) +end +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/starter_templates/elixir/code/.codecrafters/compile.sh b/starter_templates/elixir/code/.codecrafters/compile.sh new file mode 100755 index 0000000..806dc02 --- /dev/null +++ b/starter_templates/elixir/code/.codecrafters/compile.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +mix escript.build +mv codecrafters_git /tmp/codecrafters-build-git-elixir diff --git a/starter_templates/elixir/code/.codecrafters/run.sh b/starter_templates/elixir/code/.codecrafters/run.sh new file mode 100755 index 0000000..accb20c --- /dev/null +++ b/starter_templates/elixir/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec /tmp/codecrafters-build-git-elixir "$@" diff --git a/starter_templates/elixir/code/.formatter.exs b/starter_templates/elixir/code/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/starter_templates/elixir/code/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/starter_templates/elixir/code/.gitignore b/starter_templates/elixir/code/.gitignore new file mode 100644 index 0000000..881ad01 --- /dev/null +++ b/starter_templates/elixir/code/.gitignore @@ -0,0 +1,27 @@ +# Ignore the compiled binary +/codecrafters_git + +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +app-*.tar + diff --git a/starter_templates/elixir/code/lib/main.ex b/starter_templates/elixir/code/lib/main.ex new file mode 100644 index 0000000..0fee6ae --- /dev/null +++ b/starter_templates/elixir/code/lib/main.ex @@ -0,0 +1,25 @@ +defmodule CLI do + def main(argv) do + # You can use print statements as follows for debugging, they'll be visible when running tests. + IO.puts("Logs from your program will appear here!") + + # Uncomment this block to pass the first stage + # + # case argv do + # ["init" | _] -> + # :ok = File.mkdir(".git") + # :ok = File.mkdir(".git/objects") + # :ok = File.mkdir(".git/refs") + # :ok = File.write(".git/HEAD", "ref: refs/heads/main\n") + # IO.puts("Initialized git directory") + # + # [command | _] -> + # IO.puts("Unknown command: #{command}") + # System.halt(1) + # + # [] -> + # IO.puts("Usage: your_program.sh ") + # System.halt(1) + # end + end +end diff --git a/starter_templates/elixir/code/mix.exs b/starter_templates/elixir/code/mix.exs new file mode 100644 index 0000000..65acad0 --- /dev/null +++ b/starter_templates/elixir/code/mix.exs @@ -0,0 +1,30 @@ +defmodule App.MixProject do + # NOTE: You do not need to change anything in this file. + use Mix.Project + + def project do + [ + app: :codecrafters_git, + version: "1.0.0", + elixir: "~> 1.17", + start_permanent: Mix.env() == :prod, + deps: deps(), + escript: [main_module: CLI] + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/starter_templates/elixir/config.yml b/starter_templates/elixir/config.yml new file mode 100644 index 0000000..1d5ecf8 --- /dev/null +++ b/starter_templates/elixir/config.yml @@ -0,0 +1,3 @@ +attributes: + required_executable: "mix" + user_editable_file: "lib/main.ex"