{"payload":{"feedbackUrl":"https://github.com/orgs/community/discussions/53140","repo":{"id":676968379,"defaultBranch":"main","name":"gity","ownerLogin":"mohamedsaberibrahim","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2023-08-10T12:35:10.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/33963542?v=4","public":true,"private":false,"isOrgOwned":false},"refInfo":{"name":"","listCacheKey":"v0:1691670910.0","currentOid":""},"activityList":{"items":[{"before":"3e18ade8ab276a06707f2563a6815dfbb96de24e","after":"5a4de4b76b8a1c2b570316b6ed665effddc34b8b","ref":"refs/heads/main","pushedAt":"2023-10-31T06:53:48.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"docs: adding implementation roadmap to README.md","shortMessageHtmlLink":"docs: adding implementation roadmap to README.md"}},{"before":"5c61f013ffae87ceb1f888c7a436897ef1a4ea40","after":"3e18ade8ab276a06707f2563a6815dfbb96de24e","ref":"refs/heads/main","pushedAt":"2023-09-29T11:59:50.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Inject dependencies to commandOps structures\n\nTo decouple the `CommandOps` structures from the global environment and\nmake them easier to test, we replace all references to global state and\nobjects with instance variables that are passed into the `Command`\nstructures by the caller.\n\nThe replaced globals are:\n\n- `os.Getwd()`, the process's current working directory\n- `os.Getenv`, func to get environment variables\n- `args`, the command-line arguments\n- `os.Stdin`, the standard input stream\n- `os.Stdout` and `os.Stderr`, the standard output and error streams\n\nAnother tricks:\n- `fmt.Fprint` writes to the commandOps's stored `@stdout` stream, not\nthe go process's global stdout\n- `status` throws to stop the commandOps's execution, but just stores\nthe exit status rather than actually stopping go process","shortMessageHtmlLink":"Inject dependencies to commandOps structures"}},{"before":"b87fce45651479d72319d17a1ad08b3cf7b9d6ed","after":"5c61f013ffae87ceb1f888c7a436897ef1a4ea40","ref":"refs/heads/main","pushedAt":"2023-09-29T11:09:41.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Extract command code into classes\nThe code in `command` would benefit from being encapsulated in\nstructures so we can execute it from a test suite. This commit makes the\nfirst step of this process by transplanting the `command` code verbatim\nfrom its current location into one structure for each command:\n`CommandOps::Init`, `CommandOps::Add` and `CommandOps::Commit`.\n\nThe Ops structures contain exactly the same code as was previously\nin `command/` and will require further changes to make it easier to test.\nThose changes will be done in separate commits so they can be\ndistinguished from this change that just moves a lot of code around.","shortMessageHtmlLink":"Extract command code into classes"}},{"before":"fe2e9d0b65afa20a9c1d0a02ae52ad37eb469a47","after":"b87fce45651479d72319d17a1ad08b3cf7b9d6ed","ref":"refs/heads/main","pushedAt":"2023-09-29T09:34:14.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Extract command code into classes\nThe code in `command` would benefit from being encapsulated in\nstructures so we can execute it from a test suite. This commit makes the\nfirst step of this process by transplanting the `command` code verbatim\nfrom its current location into one structure for each command:\n`CommandOps::Init`, `CommandOps::Add` and `CommandOps::Commit`.\n\nThe Ops structures contain exactly the same code as was previously\nin `command/` and will require further changes to make it easier to test.\nThose changes will be done in separate commits so they can be\ndistinguished from this change that just moves a lot of code around.","shortMessageHtmlLink":"Extract command code into classes"}},{"before":"d6c423a6681c23172fe0d9f3ea2e3d1e0c8bbae8","after":"fe2e9d0b65afa20a9c1d0a02ae52ad37eb469a47","ref":"refs/heads/main","pushedAt":"2023-09-09T19:52:22.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Refactor commands code to shorter\n\nIntroduce description for long/short descriptions for commands.\nDefining runAdd, runCommit, runInit for more modularity.\nStop defining commands as a global vars","shortMessageHtmlLink":"Refactor commands code to shorter"}},{"before":"d69371488837fc364a1def3c025a427f4115e917","after":"d6c423a6681c23172fe0d9f3ea2e3d1e0c8bbae8","ref":"refs/heads/main","pushedAt":"2023-09-09T19:13:51.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Introduce the Repository class\nThe `add` and `commit` commands both begin with a lot of similar setup\nthat defines the paths to various pieces of Git infrastructure and then\ncreates objects like `Database` and `Index` around them.\n\nHere we extract this common setup into a single class that knows how to\nlocate each component on the filesystem and instantiate its class. This\ngets rid of some boilerplate from the command code and reduces the code\nwe'll need to write in each new command we add.\n\nThe methods in `Repository` are memoised, because some of the objects it\nreturns are stateful, like `Index`. Therefore, we'd like every call to\n`Repository#index` to return the same object.","shortMessageHtmlLink":"Introduce the Repository class"}},{"before":"7c59867b48bfc7367b3f62c3a31786a397aa17db","after":"d69371488837fc364a1def3c025a427f4115e917","ref":"refs/heads/main","pushedAt":"2023-09-09T19:09:34.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"fix: handle local index file\n\npassing index as a class not a pointer to class\nkills all local data and returns a fresh instance\nthat does not hold the state of the index","shortMessageHtmlLink":"fix: handle local index file"}},{"before":"cd91de26f1dd719736d5671fb4982024f6dc00c7","after":"7c59867b48bfc7367b3f62c3a31786a397aa17db","ref":"refs/heads/main","pushedAt":"2023-09-09T17:35:40.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Handle a stale index.lock existing when add is called\nIf `.git/index.lock` already exists when we want to load the index, an\nerror should be raised. Here we change `Lockfile` so that\n`hold_for_update` raises an exception rather than returning `false` if\nthe lock cannot be acquired.\n\nThis exception is then caught by the `add` command code, which prints\ninstructions for the user to remove the lock if desired.","shortMessageHtmlLink":"Handle a stale index.lock existing when add is called"}},{"before":"601620d1f7db4f766cd6d5779e7c8ff177a644a9","after":"cd91de26f1dd719736d5671fb4982024f6dc00c7","ref":"refs/heads/main","pushedAt":"2023-09-09T12:49:33.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Handle file-related errors in the add command\nWhen the user passes arguments to the `add` command, those inputs might\nrefer to filenames that do not exist, or that point to files that are\nnot readable. This set of changes makes sure such cases are handled\ngracefully.\n\nFirst, the `Workspace` class is modified to raise errors from its\n`list_files` method if the given path does not name an existing file,\nand from `read_file` and `stat_file` if the given path is not readable.\nThese errors are then caught in the `add` command code and handled so\nthat nothing is added to the database if any of the inputs name a\nmissing file.\n\nPremature exit from `add` could leave the file `.git/index.lock` in\nplace before anything is written to it, preventing further calls from\nacquiring the lock. Therefore the error handlers make sure to remove\nthis file before the program exits.","shortMessageHtmlLink":"Handle file-related errors in the add command"}},{"before":"10c24e5663fd4bee6030380f8d1344b217060ef8","after":"601620d1f7db4f766cd6d5779e7c8ff177a644a9","ref":"refs/heads/main","pushedAt":"2023-09-09T09:54:49.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Discard index files whose directories collide with files\nIf the index contains the following files:\n\n alice.txt\n nested/bob.txt\n nested/inner/claire.txt\n\nand a file named `nested` is added, then the entries `nested/bob.txt`\nand `nested/inner/claire.txt` should be removed, since the name `nested`\nnow corresponds to a file, not a directory.\n\nBy adding a new structure to `Index` that tracks all the entries that\nare downstream of a particular directory, we make it easy to identify\nentries that must be removed when one of their parent directories is\nreplaced by a file.","shortMessageHtmlLink":"Discard index files whose directories collide with files"}},{"before":"53f3d19a95a4cf377dd69e0b953f5af9f60a7edc","after":"10c24e5663fd4bee6030380f8d1344b217060ef8","ref":"refs/heads/main","pushedAt":"2023-09-09T09:34:16.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Discard index files when replaced with directories\nIf the index contains the following files:\n\n alice.txt\n bob.txt\n\nand a file named `alice.txt/nested.txt` is added, then the entry\n`alice.txt` should be removed, since that name now corresponds to a\ndirectory containing the new file.\n\nWe accomplish this by iterating over the newly added entry's parent\ndirectories, and removing any entries whose names are equal to any of\nthem.","shortMessageHtmlLink":"Discard index files when replaced with directories"}},{"before":"a849140efd86d13af8137b4491eec478f54c0acd","after":"53f3d19a95a4cf377dd69e0b953f5af9f60a7edc","ref":"refs/heads/main","pushedAt":"2023-09-09T09:31:09.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Discard index files when replaced with directories\nIf the index contains the following files:\n\n alice.txt\n bob.txt\n\nand a file named `alice.txt/nested.txt` is added, then the entry\n`alice.txt` should be removed, since that name now corresponds to a\ndirectory containing the new file.\n\nWe accomplish this by iterating over the newly added entry's parent\ndirectories, and removing any entries whose names are equal to any of\nthem.","shortMessageHtmlLink":"Discard index files when replaced with directories"}},{"before":"3d5a5a551bd7f6b07fe45590214985bead1f07c9","after":"a849140efd86d13af8137b4491eec478f54c0acd","ref":"refs/heads/main","pushedAt":"2023-09-09T09:27:10.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Begin adding unit tests\nTo get a simple test suite in place, this adds a single test for adding\nan entry to the index. The tests are written using testing and reflect.\n\nWe don't need to clean up files after the test because we don't tell the\nindex to write to disk at any point.","shortMessageHtmlLink":"Begin adding unit tests"}},{"before":"ab1750b1ff669d7a155a7b91942f0fa16684f738","after":"3d5a5a551bd7f6b07fe45590214985bead1f07c9","ref":"refs/heads/main","pushedAt":"2023-09-06T20:43:14.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Use the index to build the next commit\nHere we migrate the `commit` command from using the `Workspace` to using\nthe `Index` to build the tree for the new commit. Rather than reading\nthe entire project from disk and hashing it, we read the cached blob IDs\nfrom `.git/index` and use those to build a tree.\n\nThe data structures created by `Index` and `Index::Entry` are quite\nsimilar to the original `Entry` class. The only difference is the\naddition of some convenience methods for accessing the basename and\nparent directories of the entry's path.","shortMessageHtmlLink":"Use the index to build the next commit"}},{"before":"105099f02c88f1aebd4718610a84f1e457da077c","after":"ab1750b1ff669d7a155a7b91942f0fa16684f738","ref":"refs/heads/main","pushedAt":"2023-09-05T22:16:38.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Incrementally update the index\nRather than overwriting whatever is currently stored in `.git/index`,\nthe `add` command should read whatever is on disk, modify it, and then\nwrite it back, all while holding a lock on the index file.\n\nHere we add parsing logic to read the index data we've been writing\nusing the last few commits, taking care to validate the signature,\nversion and checksum as we go. We're currently ignoring the path length\nfield and just scanning in blocks of 8 bytes until we find the null\nterminator.","shortMessageHtmlLink":"Incrementally update the index"}},{"before":"986ed4f1a035368c673cb7851e8abc39c6661ed5","after":"105099f02c88f1aebd4718610a84f1e457da077c","ref":"refs/heads/main","pushedAt":"2023-09-04T20:38:00.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Support passing directory names to add\nThis change allows the `add` command to accept directory names as well\nas names of files, and it will add everything inside that directory to\nthe index. This requires a change to `Workspace#list_files` to expand\nboth file and directory names into a list of everything matching them.","shortMessageHtmlLink":"Support passing directory names to add"}},{"before":"5b96344a7071ed0d3102e8ec844862dfea7a53c6","after":"986ed4f1a035368c673cb7851e8abc39c6661ed5","ref":"refs/heads/main","pushedAt":"2023-09-04T19:48:07.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Allow add to take multiple filenames\nWe'd like to be able to add all the files in the project to the index.\nSince we don't yet support incremental updates to the index, one easy\nway to support this would be to allow the `add` command to take multiple\nfilenames. We can then run a command like:\n\n $ gity add $(find bin lib -type f)\n\nto write an index containing all the project files.","shortMessageHtmlLink":"Allow add to take multiple filenames"}},{"before":"9f247a075edc1f6452336265d1f7505e74badd74","after":"5b96344a7071ed0d3102e8ec844862dfea7a53c6","ref":"refs/heads/main","pushedAt":"2023-09-03T20:56:04.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"An add command for writing a single file to the index\nHere we begin to build up the machinery necessary for the `add` command.\nIn this first pass, it takes a single file path, writes that file's\ncontents to the database, and stores the resulting ID and stat data in\nthe index.\n\nThe process overwrites whatever the index currently contains. We don't\nyet have code for reading the index and modifying it; we just build a\nnew empty `Index` in memory, add a single entry to it, and write it to\ndisk.\n\nHowever, the serialisation logic present here is largely complete: the\n`Index::Entry` class writes all the necessary stat information out,\nincluding the file mode for executables, the blob ID is recorded\ncorrectly, and the index is finished with a SHA-1 hash. Comparison of\nthis implementation with Git shows that the resulting `.git/index`\ncontents are byte-for-byte identical after adding a single file.\n\nThe index is not yet used to build commits -- the `commit` command still\nreads directly from the working tree.","shortMessageHtmlLink":"An add command for writing a single file to the index"}},{"before":"41dd9ba20931b64af9b5803cf2d6f0751f74f9a5","after":"9f247a075edc1f6452336265d1f7505e74badd74","ref":"refs/heads/main","pushedAt":"2023-09-02T12:11:47.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Store nested trees in the object database\nCurrently, each commit contains only a single tree that contains a flat\nlist of blobs. To store projects with subdirectories, we need to write\nnested trees to the database.\n\nThese paths are stored off as blobs and wrapped in `Entry` objects in\nthe usual way. This list is then turned into a nested structure by\n`Tree.Build`, and we scan this structure using `Tree#traverse`\nto store off all the subtrees. Saving each subtree gives it an object ID\nthat allows it to be listed in its parent tree.","shortMessageHtmlLink":"Store nested trees in the object database"}},{"before":"22d8c8bbd1a681e1910ded17280c033af3e29801","after":"41dd9ba20931b64af9b5803cf2d6f0751f74f9a5","ref":"refs/heads/main","pushedAt":"2023-08-24T05:41:06.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Record the mode of executable files\nSo far, all tree entries have had their mode hard-coded to `100644`, the\nmode of regular files. In order to store the fact a file is executable,\nwe must store it using the mode `100755`.\n\nHere we achieve that by calling `stat(2)` on each file when we store\nblobs into the database, and passing the stat into the `Entry` class.\nWhen we serialize a `Tree` object, rather than hard-coding the mode of\neach entry as `100644`, we ask the entry for its mode, which it chooses\nby using the file stat to check if the file is executable by the current\nuser.","shortMessageHtmlLink":"Record the mode of executable files"}},{"before":"8e16a9dccd4b39964dc6128f957f375393dc8bd7","after":"22d8c8bbd1a681e1910ded17280c033af3e29801","ref":"refs/heads/main","pushedAt":"2023-08-23T19:12:44.000Z","pushType":"push","commitsCount":3,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Don't overwrite database objects\nNow that we're forming a chain of commits, some of the blobs will be the\nsame from one tree to the next. It's wasteful to spend time writing\nfiles to `.gity/objects` when they already exist, so we'll put in a check\nfor the object existing before beginning to write it.\n\nThis is also part of the mitigation against SHA-1 collisions being\nexploited; we always keep the object we have rather than overwriting it\nwith something else.","shortMessageHtmlLink":"Don't overwrite database objects"}},{"before":"1e29f2f84fa1cb0555e52f82cc6106e178f2202b","after":"8e16a9dccd4b39964dc6128f957f375393dc8bd7","ref":"refs/heads/main","pushedAt":"2023-08-21T06:38:53.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Initial revision of \"gity\"\nThis commit records a minimal set of functionality necessary for the\ncode to store itself as a valid Git commit. This includes writing the\nfollowing object types to the database:\n\n- Blobs of ASCII text\n- Trees containing a flat list of regular files\n- Commits that contain a tree pointer, author info and message\n\nThese objects are written to `.gity/objects`, compressed using zlib.\n\nAt this stage, there is no index and no `add` command; the `commit`\ncommand simply writes everything in the working tree to the database and\ncommits it.","shortMessageHtmlLink":"Initial revision of \"gity\""}},{"before":"e833c7b2f826d3a084210c58f5dbf27acacc5355","after":"1e29f2f84fa1cb0555e52f82cc6106e178f2202b","ref":"refs/heads/main","pushedAt":"2023-08-17T05:21:34.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"initial commit - adding cobra-cli setup","shortMessageHtmlLink":"initial commit - adding cobra-cli setup"}},{"before":null,"after":"e833c7b2f826d3a084210c58f5dbf27acacc5355","ref":"refs/heads/main","pushedAt":"2023-08-10T12:35:10.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"mohamedsaberibrahim","name":"Mohamed Saber","path":"/mohamedsaberibrahim","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/33963542?s=80&v=4"},"commit":{"message":"Initial commit","shortMessageHtmlLink":"Initial commit"}}],"hasNextPage":false,"hasPreviousPage":false,"activityType":"all","actor":null,"timePeriod":"all","sort":"DESC","perPage":30,"cursor":"djE6ks8AAAADo7kLCQA","startCursor":null,"endCursor":null}},"title":"Activity ยท mohamedsaberibrahim/gity"}