6.7 KiB
Assignment 1
due on 18 November 2020
In this first assignment your task is to create a version control system (VCS) similar to Git or Mercurial. However, this VCS will be much simpler.
For this assignment you are not allowed to work in teams. You are not allowed to use code from other people participating in this course. Always state the origin of non-original code and ideas.
It is recommend to be familiar with Git to understand the intensions behind the following commands.
lit
All functionality of your VCS is bundled into one executable named lit
.
Similar to git
, it provides multiple sub-commands like checkout
and status
.
These sub-commands are always provided as first argument to lit
and explained below.
lit help
Displays a concise usage information. Each sub-command is listed and described briefly.
lit init
To initialize a repository run lit init
inside some directory.
This directory is now the root of the repository.
Additionally, the VCS creates a new folder .lit
containing all internal data.
All files of the directory are tracked. There is no need to explicitly add them as you'd do with Git.
lit status
Lists all files that have been added, removed, or modified, with respect to the currently checked out commit.
Keep the output concise, similar to git status --short
.
lit commit
Creates a new commit containing all changes. In contrast to Git, there is no staging area.
A commit is comprised of a unique identifier, the identifier of the parent commit(s), a timestamp, a message, and the recorded changes.
The message is provided to the commit
sub-command as additional argument.
Use a counter (starting from 0) prefixed with r
(for revision) as unique identifier.
$ lit commit 'Add coin operated self-destruct feature'
Commit: r42
Date: Mon Sep 28 23:27:53 CEST 2020
lit show
This sub-command is used to inspect the given commit. If no commit is specified, display the currently checked out one.
$ lit show r42
Commit: r42
Parents: r41
Date: Mon Sep 28 23:27:53 CEST 2020
Add coin operated self-destruct feature
--- a/main.c
+++ b/main.c
@@ -1,8 +1,19 @@
#include <stdio.h>
#include <stdlib.h>
+#include "ship_systems/propulsion/shaw_fujikawa.h"
+
+#include "utils/coin_operator.h"
+
int main(void)
{
puts("Hello World");
+
+ if (coin_operator_triggered()) {
+ puts("Have a nice day (> . =)");
+ prop_engine_t *engine = prop_ftl_get_shaw_fujikawa();
+ prop_detonate(engine);
+ }
+
return EXIT_SUCCESS;
}
lit checkout
This resets the state of all files to the given commit's state. All un-committed changes are dropped upon checkout.
If no commit is specified, reset the current state to the currently checked out commit.
You can add new branches by first checking out a previous commit, and then creating a new commit.
lit merge
This command initiates a merge with the currently checked out commit and the specified commit. A merge is only initiated if there are no un-committed changes.
Auto-merging files that have been touched in both branches is not supported. If a file has been modified in both branches, the whole file is treated as a conflict.
If a conflict is encountered, stop the merge process and provide the respective files of the other branch as well as the common base.
$ lit merge r21
Merge conflict(s) detected:
- robot.c
$ ls
robot.c # currently checked out version.
robot.c.r21 # version of the other branch
robot.c.r18 # common base of both branches
$ # Manually resolving the merge conflict:
$ vimdiff robot.c robot.c.r21 robot.c.r18
$ # Cleanup
$ rm robot.c.r21 robot.c.r18
$ lit commit 'Merge r21 into r20'
To complete the merge after manually resolving a conflict, invoke the commit
sub-command.
To abort the merge, use checkout
.
lit log
Displays a graph of all commits, one line per commit. The currently checked out commit is highlighted.
You don't have to follow the exact format of this example:
$ lit log
o←┐ ← r3 "Merge r2 with r1"
│ └o r2 "Add chocolate egg dispenser"
o │ r1 "Add coin operated self destruct feature"
o──┘ r0 "First Commit"
Implementation
If you encounter a problem where the specification is ambiguous or unclear, make a justifiable decision on what to do.
You are only allowed to use:
- C++ standard library (C++17 standard)
- C standard library (as fallback)
- GNU/Linux operating system's C APIs (POSIX,
mmap
, memfd, eventfd, …) diff
/patch
command
You must use CMake as build system.
Use ClangFormat to automatically format your code using the provided .clang-format
configuration.
There is probably a plugin for your text editor / IDE to automate this process.
Your VCS must store the differences (as reported by diff -u
).
Storing a full copy of the repository's files for each commit is not allowed.
You don't need to track empty folders, yet files located within folders.
You may treat empty files as being deleted.
You may assume that lit
is always executed from the root of a repository.
You may assume that only one instance of your VCS operates on a repository at any point in time. Hence, you don't need to add some form of locking mechanism to prevent concurrent access.
The executable does not depend on any additional resources (except for standard libraries, diff
and patch
).
You may assume that diff
and patch
are present and available via PATH
.
Hint: It may be a good idea to create a dedicated class for invoking shell commands like diff
and patch
.
Simply using system(3)
may not give you enough control over the process as you also need to interact with stdin
/ stdout
.
Consider using popen(3)
(or even fork(2)
, exec(2)
, pipe(2)
, and dup2(2)
) and getting some inspiration from Go's exec
package or Python's subprocess
module.
Testing
Along with this specification a rudimentary test script lit-test
is provided, have a look at it.
It assumes that the lit
executable is in your path.
Remember that you can use bash -x
to debug the test script.
You are encouraged to set up some more test cases for your implementation.
Evaluation (9 points)
- (3) Can create new commits and checkout old ones (no branches)
- (2) Can create new branches and switch between branches
- (1) Can inspect a commit using
lit show
- (1) Can merge two branches (no conflict)
- (1) Can merge two branches (with conflict)
- (1) Can display a graph with all commits and their relationships
Submission
TBD