Skip to content

Commit 864c10d

Browse files
authored
Merge pull request #157 from codecrafters-io/extract-stage-descriptions
Extract stage descriptions to markdown files
2 parents d160835 + e6e2cb2 commit 864c10d

File tree

8 files changed

+724
-732
lines changed

8 files changed

+724
-732
lines changed

course-definition.yml

Lines changed: 0 additions & 732 deletions
Large diffs are not rendered by default.

stage_descriptions/base-01-gg4.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
In this stage, you'll implement the `git init` command.
2+
3+
### The `git init` command
4+
5+
<details>
6+
<summary>Click to expand/collapse</summary>
7+
8+
`git init` initializes a Git repository by creating a `.git` directory with some files
9+
& directories inside it.
10+
11+
You can learn more about what's inside the `.git` folder [here](https://blog.meain.io/2023/what-is-in-dot-git/). We've
12+
included a description of the files & directores we'll be dealing with in this stage below.
13+
14+
</details>
15+
16+
### The `.git` directory
17+
18+
<details>
19+
<summary>Click to expand/collapse</summary>
20+
21+
At a bare minimum, a `.git` directory should contain the following files & directories:
22+
23+
```
24+
- .git/
25+
- objects/
26+
- refs/
27+
- HEAD (should contain "ref: refs/heads/main\n" for a new repository)
28+
```
29+
30+
- `objects/`
31+
- This directory contains [Git objects](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects).
32+
- We'll learn more about what Git objects are in later stages.
33+
- `refs/`
34+
- This directory contains [Git references](https://git-scm.com/book/en/v2/Git-Internals-Git-References).
35+
- We'll deal with this in later stages too.
36+
- `HEAD`
37+
- This file contains a reference to the currently checked out branch.
38+
- For a new repository, it's contents will be `ref: refs/heads/main\n`.
39+
40+
You can learn more about these in detail [here](https://blog.meain.io/2023/what-is-in-dot-git/).
41+
</details>
42+
43+
### Tests
44+
45+
The tester will run your program in a new empty directory like this:
46+
47+
```bash
48+
# Create a new directory and cd into it
49+
$ mkdir test_dir && cd test_dir
50+
51+
# Run your program
52+
$ /path/to/your_program.sh init
53+
```
54+
55+
It'll then check if the `.git` directory and its contents are created correctly.
56+
57+
```bash
58+
# Check if .git directory exists
59+
$ test -d .git
60+
61+
# Check if .git/objects directory exists
62+
$ test -d .git/objects
63+
64+
# Check if .git/refs directory exists
65+
$ test -d .git/refs
66+
67+
# Check if .git/HEAD file exists
68+
$ test -f .git/HEAD
69+
70+
# Check if .git/HEAD contains either "ref: refs/heads/main\n" or "ref: refs/heads/master\n"
71+
$ cat .git/HEAD
72+
```
73+
74+
### Notes
75+
76+
- Git actually creates more files & directories than the ones mentioned above when you run `git init`. We've only included the ones
77+
that are absolutely necessary for Git to function properly.
78+
- The `.git/HEAD` file has a newline at the end.
79+
- The `.git/HEAD` file can contain either `ref: refs/heads/main\n` or `ref: refs/heads/master\n`, the tester will
80+
work with either of these.

stage_descriptions/base-02-ic4.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
In this stage, you'll add support for reading a blob using the `git cat-file` command.
2+
3+
### Git objects
4+
5+
<details>
6+
<summary>Click to expand/collapse</summary>
7+
8+
In this challenge, we'll deal with three [Git
9+
objects](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects):
10+
11+
- Blobs (**This stage**)
12+
- These are used to store file data.
13+
- Blobs only store the contents of a file, not its name or permissions.
14+
- Trees (Future stages)
15+
- These are used to store directory structures.
16+
- The information stored can include things like what files/directories are in a tree, their names and permissions.
17+
- Commits (Future stages)
18+
- These are used to store commit data.
19+
- The information stored can include things like the commit message, author, committer, parent commit(s) and more.
20+
21+
22+
All Git objects are identifiable by a 40-character SHA-1 hash, also known as the "object hash".
23+
24+
Here's an example of an object hash: `e88f7a929cd70b0274c4ea33b209c97fa845fdbc`.
25+
</details>
26+
27+
### Git Object Storage
28+
29+
<details>
30+
<summary>Click to expand/collapse</summary>
31+
32+
Git objects are stored in the `.git/objects` directory. The path to an object is derived from its hash.
33+
34+
The path for the object with the hash `e88f7a929cd70b0274c4ea33b209c97fa845fdbc` would be:
35+
36+
```bash
37+
.git/objects/e8/8f7a929cd70b0274c4ea33b209c97fa845fdbc
38+
```
39+
40+
You'll see that the file isn't placed directly in the `.git/objects` directory. Instead, it's placed in a directory named with the
41+
first two characters of the object's hash. The remaining 38 characters are used as the file name.
42+
43+
Each Git object has its own format for storage. We'll look at how Blobs are stored in this stage, and we'll cover
44+
other objects in future stages.
45+
</details>
46+
47+
### Blob Object Storage
48+
49+
<details>
50+
<summary>Click to expand/collapse</summary>
51+
52+
Each Git Blob is stored as a separate file in the `.git/objects` directory. The file contains a header and the contents of
53+
the blob object, compressed using Zlib.
54+
55+
The format of a blob object file looks like this (after Zlib decompression):
56+
57+
```
58+
blob <size>\0<content>
59+
```
60+
61+
- `<size>` is the size of the content (in bytes)
62+
- `\0` is a null byte
63+
- `<content>` is the actual content of the file
64+
65+
For example, if the contents of a file are `hello world`, the blob object file would look like this (after Zlib decompression):
66+
67+
```
68+
blob 11\0hello world
69+
```
70+
</details>
71+
72+
### The cat-file command
73+
74+
<details>
75+
<summary>Click to expand/collapse</summary>
76+
77+
In this stage, you'll read a blob from a git repository by reading its contents from the `.git/objects` directory.
78+
79+
You'll do this using the first of multiple ["plumbing" commands](https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain)
80+
we'll encounter in this challenge: [`git cat-file`](https://git-scm.com/docs/git-cat-file).
81+
82+
`git cat-file` is used to view the type of an object, its size, and its content. Example usage:
83+
84+
```bash
85+
$ git cat-file -p <blob_sha>
86+
hello world # This is the contents of the blob
87+
```
88+
89+
To implement this, you'll need to:
90+
91+
- Read the contents of the blob object file from the `.git/objects` directory
92+
- Decompress the contents using Zlib
93+
- Extract the actual "content" from the decompressed data
94+
- Print the content to stdout
95+
96+
</details>
97+
98+
### Tests
99+
100+
The tester will first initialize a new git repository using your program, and then insert a blob with random contents into the `.git/objects` directory:
101+
102+
```bash
103+
$ mkdir /tmp/test_dir && cd /tmp/test_dir
104+
$ /path/to/your_program.sh init
105+
$ echo "hello world" > test.txt # The tester will use a random string, not "hello world"
106+
$ git hash-object -w test.txt
107+
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
108+
```
109+
110+
After that, it'll run your program like this:
111+
112+
```bash
113+
$ /path/to/your_program.sh cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dad
114+
hello world
115+
```
116+
117+
The tester will verify that the output of your program matches the contents of the blob.
118+
119+
### Notes
120+
121+
- In many programming languages the default print function (like [`fmt.Println`](https://pkg.go.dev/fmt#example-Println))
122+
will append a newline to the output. The output of `cat-file` must not contain a
123+
newline at the end, so you might need to use a different function to print the output.
124+
125+
{{#lang_is_python}}
126+
- Keep in mind that Git uses [Zlib](https://en.wikipedia.org/wiki/Zlib) to
127+
compress objects. You can use Python's built-in
128+
[zlib](https://docs.python.org/3/library/zlib.html) library to read these
129+
compressed files.
130+
{{/lang_is_python}}
131+
132+
{{#lang_is_ruby}}
133+
- Keep in mind that Git uses [Zlib](https://en.wikipedia.org/wiki/Zlib) to
134+
compress objects. You can use Ruby's built-in
135+
[Zlib](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib.html)
136+
library to read these compressed files.
137+
{{/lang_is_ruby}}
138+
139+
{{#lang_is_go}}
140+
- Keep in mind that Git uses [Zlib](https://en.wikipedia.org/wiki/Zlib) to
141+
compress objects. You can use Go's built-in
142+
[compress/zlib](https://golang.org/pkg/compress/zlib/) package to read
143+
these compressed files.
144+
{{/lang_is_go}}
145+
146+
{{#lang_is_rust}}
147+
- Keep in mind that Git uses [Zlib](https://en.wikipedia.org/wiki/Zlib) to
148+
compress objects. You can use the
149+
[flate2](https://crates.io/crates/flate2) crate to read these compressed
150+
files, we've included it in the `Cargo.toml` file.
151+
{{/lang_is_rust}}
152+
153+
{{^lang_is_python}}
154+
{{^lang_is_ruby}}
155+
{{^lang_is_go}}
156+
{{^lang_is_rust}}
157+
- Keep in mind that Git uses [Zlib](https://en.wikipedia.org/wiki/Zlib) to
158+
compress objects. Many languages have utils for dealing with zlib data in their standard library. If not,
159+
you might need to use a third-party library to read these compressed files.
160+
{{/lang_is_rust}}
161+
{{/lang_is_go}}
162+
{{/lang_is_ruby}}
163+
{{/lang_is_python}}

stage_descriptions/base-03-jt4.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
In this stage, you'll implement support for creating a blob using the [`git
2+
hash-object`](https://git-scm.com/docs/git-hash-object) command.
3+
4+
### The `git hash-object` command
5+
6+
<details>
7+
<summary>Click to expand/collapse</summary>
8+
9+
`git hash-object` is used to compute the SHA-1 hash of a Git object. When used with the `-w` flag, it
10+
also writes the object to the `.git/objects` directory.
11+
12+
Here's an example of using `git hash-object`:
13+
14+
```bash
15+
# Create a file with some content
16+
$ echo -n "hello world" > test.txt
17+
18+
# Compute the SHA-1 hash of the file + write it to .git/objects
19+
$ git hash-object -w test.txt
20+
95d09f2b10159347eece71399a7e2e907ea3df4f
21+
22+
# Verify that the file was written to .git/objects
23+
$ file .git/objects/95/d09f2b10159347eece71399a7e2e907ea3df4f
24+
.git/objects/95/d09f2b10159347eece71399a7e2e907ea3df4f: zlib compressed data
25+
```
26+
27+
</details>
28+
29+
### Blob Object Storage (Recap)
30+
31+
<details>
32+
<summary>Click to expand/collapse</summary>
33+
34+
As mentioned in the previous stage, each Git Blob is stored as a separate file in the `.git/objects` directory. The file
35+
contains a header and the contents of the blob object, compressed using Zlib.
36+
37+
The format of a blob object file looks like this (after Zlib decompression):
38+
39+
```
40+
blob <size>\0<content>
41+
```
42+
43+
- `<size>` is the size of the content (in bytes)
44+
- `\0` is a null byte
45+
- `<content>` is the actual content of the file
46+
47+
For example, if the contents of a file are `hello world`, the blob object file would look like this (after Zlib decompression):
48+
49+
```
50+
blob 11\0hello world
51+
```
52+
53+
</details>
54+
55+
### Tests
56+
57+
The tester will first initialize a new git repository using your program:
58+
59+
```bash
60+
$ mkdir test_dir && cd test_dir
61+
$ /path/to/your_program.sh init
62+
```
63+
64+
It'll write some random data to a file:
65+
66+
```bash
67+
$ echo "hello world" > test.txt
68+
```
69+
70+
It'll then run your program like this:
71+
72+
```bash
73+
$ ./your_program.sh hash-object -w test.txt
74+
3b18e512dba79e4c8300dd08aeb37f8e728b8dad
75+
```
76+
77+
The tester will verify that:
78+
79+
- Your program prints a 40-character SHA-1 hash to stdout
80+
- The file written to `.git/objects` matches what the official `git` implementation would write
81+
82+
### Notes
83+
84+
- Although the object file is stored with zlib compression, the SHA-1 hash needs to be computed over
85+
the "uncompressed" contents of the file, not the compressed version.
86+
- The input for the SHA-1 hash is the header (`blob <size>\0`) + the actual contents of the file,
87+
not just the contents of the file.
88+
{{#lang_is_c}}
89+
- You can use `#include <openssl/sha.h>` to access OpenSSL’s [SHA1()](https://www.openssl.org/docs/man3.0/man3/SHA1.html) hashing function.
90+
{{/lang_is_c}}
91+
{{#lang_is_cpp}}
92+
- You can use `#include <openssl/sha.h>` to access OpenSSL’s [SHA1()](https://www.openssl.org/docs/man3.0/man3/SHA1.html) hashing function.
93+
{{/lang_is_cpp}}

0 commit comments

Comments
 (0)