예제 #1
0
        public override int Run(string[] remainingArguments)
        {
            var message = Gitlet.Status();

            Console.WriteLine(message);
            return(0);
        }
예제 #2
0
 /// <summary>
 /// Fetches the commit that `branch` is on at `remote`.
 /// It merges that commit into the current branch.
 /// </summary>
 public static string Pull(string remote, string branch)
 {
     Files.AssertInRepo();
     Config.AssertNotBare();
     Gitlet.Fetch(remote, branch);
     return(Gitlet.Merge("FETCH_HEAD"));
 }
예제 #3
0
        public override int Run(string[] remainingArguments)
        {
            var path = remainingArguments[0];

            Gitlet.Add(path);
            return(0);
        }
예제 #4
0
 public override int Run(string[] remainingArguments)
 {
     Gitlet.Init(new InitOptions {
         Bare = Bare
     });
     return(0);
 }
예제 #5
0
        public override int Run(string[] remainingArguments)
        {
            var    options = new LogOptions();
            string message = Gitlet.Log(options);

            Console.WriteLine(message);
            return(0);
        }
예제 #6
0
        public override int Run(string[] remainingArguments)
        {
            var command = remainingArguments[0];
            var name    = remainingArguments[1];
            var url     = remainingArguments[2];

            Gitlet.Remote(command, name, url);
            return(0);
        }
예제 #7
0
        public override int Run(string[] remainingArguments)
        {
            var remote = remainingArguments[0];

            var message = Gitlet.Fetch(remote, null);

            Console.WriteLine(message);
            return(0);
        }
예제 #8
0
        public override int Run(string[] remainingArguments)
        {
            var repository = remainingArguments[0];
            var branch     = remainingArguments[1];
            var message    = Gitlet.Pull(repository, branch);

            Console.WriteLine(message);
            return(0);
        }
예제 #9
0
        public override int Run(string[] remainingArguments)
        {
            var options = new CommitOptions {
                m = Message
            };
            var message = Gitlet.Commit(options);

            Console.WriteLine(message);
            return(0);
        }
예제 #10
0
        public override int Run(string[] remainingArguments)
        {
            var path    = remainingArguments[0];
            var options = new RmOptions {
                f = Force, r = Recursive
            };

            Gitlet.Rm(path, options);
            return(0);
        }
예제 #11
0
        public override int Run(string[] remainingArguments)
        {
            var remotePath = remainingArguments[0];
            var targetPath = remainingArguments[1];

            var message = Gitlet.Clone(remotePath, targetPath, new CloneOptions {
                Bare = Bare
            });

            Console.WriteLine(message);
            return(0);
        }
예제 #12
0
        public static string Clone(string remotePath, string targetPath, CloneOptions options = null)
        {
            options = options ?? new CloneOptions();

            // Abort if a `remotePath` or `targetPath` not passed.
            if (remotePath == null)
            {
                throw new ArgumentNullException("remotePath");
            }
            if (targetPath == null)
            {
                throw new ArgumentNullException("targetPath");
            }

            // Abort if `remotePath` does not exist, or is not a Gitlet
            // repository. !util.remote(remotePath)(files.inRepo))
            if (!Directory.Exists(remotePath) || !Util.Remote <bool>(remotePath)(Files.InRepo))
            {
                throw new Exception("repository " + remotePath + " does not exist");
            }

            // Abort if `targetPath` exists and is not empty.
            targetPath = Files.Absolute(targetPath);
            var targetDir = new DirectoryInfo(targetPath);

            if (targetDir.Exists && targetDir.GetFileSystemInfos().Length > 0)
            {
                throw new Exception(targetPath + " already exists and is not empty");
            }

            // Otherwise, do the clone.
            remotePath = Files.Absolute(remotePath);

            // If `targetPath` doesn't exist, create it.
            if (!targetDir.Exists)
            {
                targetDir.Create();
            }

            Util.Remote <object>(targetPath)(() =>
            {
                // Initialize the directory as a Gitlet repository.
                Gitlet.Init(options);

                // Set up `remotePath` as a remote called "origin".
                Gitlet.Remote("add", "origin", Files.Relative(Files.CurrentPath, remotePath));

                // Get the hash of the commit that master is pointing at on
                // the remote repository.
                var remoteHeadHash = Util.Remote <string>(remotePath)(() => Refs.Hash("master"));

                // If the remote repo has any commits, that hash will exist.
                // The new repository records the commit that the passed
                // `branch` is at on the remote.  It then sets master on the
                // new repository to point at that commit.
                if (remoteHeadHash != null)
                {
                    Gitlet.Fetch("origin", "master");
                    Core.Merge.WriteFastForwardMerge(null, remoteHeadHash);
                }

                return(null);
            });

            // Report the result of the clone.
            return("Cloning into " + targetPath);
        }
예제 #13
0
        public static string Merge(string @ref)
        {
            Files.AssertInRepo();
            Config.AssertNotBare();

            // Get the `receiverHash`, the hash of the commit that the
            // current branch is on.
            var receiverHash = Refs.Hash("HEAD");

            // Get the `giverHash`, the hash for the commit to merge into the
            // receiver commit.
            var giverHash = Refs.Hash(@ref);

            // Abort if head is detached.  Merging into a detached head is not
            // supported.
            if (Refs.IsHeadDetached())
            {
                throw new Exception("unsupported");
            }

            // Abort if `ref` did not resolve to a hash, or if that hash is
            // not for a commit object.
            if (giverHash == null || Objects.Type(Objects.Read(giverHash)) != "commit")
            {
                throw new Exception(@ref + ": expected commit type");
            }

            // Do not merge if the current branch - the receiver - already has
            // the giver's changes.  This is the case if the receiver and
            // giver are the same commit, or if the giver is an ancestor of
            // the receiver.
            if (Objects.IsUpToDate(receiverHash, giverHash))
            {
                return("Already up-to-date");
            }

            // Get a list of files changed in the working copy.  Get a list
            // of the files that are different in the receiver and giver. If
            // any files appear in both lists then abort.
            var paths = Diff.ChangedFilesCommitWouldOverwrite(giverHash);

            if (paths.Length > 0)
            {
                throw new Exception("local changes would be lost\n" + string.Join("\n", paths) + "\n");
            }

            // If the receiver is an ancestor of the giver, a fast forward
            // is performed.  This is possible because there is already a
            // commit that incorporates all of the giver's changes into the
            // receiver.
            if (Core.Merge.CanFastForward(receiverHash, giverHash))
            {
                // Fast forwarding means making the current branch reflect the
                // commit that `giverHash` points at.  The branch is pointed
                // at `giverHash`.  The index is set to match the contents of
                // the commit that `giverHash` points at.  The working copy is
                // set to match the contents of that commit.
                Core.Merge.WriteFastForwardMerge(receiverHash, giverHash);
                return("Fast-forward");
            }

            // If the receiver is not an ancestor of the giver, a merge
            // commit must be created.

            // The repository is put into the merge state.  The
            // `MERGE_HEAD` file is written and its contents set to
            // `giverHash`.  The `MERGE_MSG` file is written and its
            // contents set to a boilerplate merge commit message.  A
            // merge diff is created that will turn the contents of
            // receiver into the contents of giver.  This contains the
            // path of every file that is different and whether it was
            // added, removed or modified, or is in conflict.  Added files
            // are added to the index and working copy.  Removed files are
            // removed from the index and working copy.  Modified files
            // are modified in the index and working copy.  Files that are
            // in conflict are written to the working copy to include the
            // receiver and giver versions.  Both the receiver and giver
            // versions are written to the index.
            Core.Merge.WriteNonFastForwardMerge(receiverHash, giverHash, @ref);

            // If there are any conflicted files, a message is shown to
            // say that the user must sort them out before the merge can
            // be completed.
            if (Core.Merge.HasConflicts(receiverHash, giverHash))
            {
                return("Automatic merge failed. Fix conflicts and commit the result.");
            }

            return(Gitlet.Commit(new CommitOptions()));
        }
예제 #14
0
        /// <summary>
        /// records the commit that `branch` is at on `remote`.
        // It does not change the local branch.
        /// </summary>
        public static string Fetch(string remote, string branch)
        {
            Files.AssertInRepo();

            // Abort if a `remote` or `branch` not passed.
            if (remote == null || branch == null)
            {
                throw new Exception("unsupported");
            }

            // Abort if `remote` not recorded in config file.
            if (!Config.Read().Remotes.ContainsKey(remote))
            {
                throw new Exception(remote + " does not appear to be a git repository");
            }

            // Get the location of the remote.
            var remoteUrl = Files.Absolute(Config.Read().Remotes[remote].Url);

            // Turn the unqualified branch name into a qualified remote ref
            // eg `[branch] -> refs/remotes/[remote]/[branch]`
            var remoteRef = Refs.ToRemoteRef(remote, branch);

            // Go to the remote repository and get the hash of the commit
            // that `branch` is on.
            var newHash = Util.Remote <string>(remoteUrl)(() => Refs.Hash(branch));

            // Abort if `branch` did not exist on the remote.
            if (newHash == null)
            {
                throw new Exception("couldn't find remote ref " + branch);
            }

            // Otherwise, perform the fetch.

            // Note down the hash of the commit this repository currently
            // thinks the remote branch is on.
            var oldHash = Refs.Hash(remoteRef);

            // Get all the objects in the remote `objects` directory and
            // write them.  to the local `objects` directory.  (This is an
            // inefficient way of getting all the objects required to
            // recreate locally the commit the remote branch is on.)
            var remoteObjects = Util.Remote <string[]>(remoteUrl)(Objects.AllObjects);

            foreach (var remoteObject in remoteObjects)
            {
                Objects.Write(remoteObject);
            }

            // Set the contents of the file at
            // `.gitlet/refs/remotes/[remote]/[branch]` to `newHash`, the
            // hash of the commit that the remote branch is on.
            Gitlet.UpdateRef(remoteRef, newHash);

            // Record the hash of the commit that the remote branch is on
            // in `FETCH_HEAD`.  (The user can call `gitlet merge
            // FETCH_HEAD` to merge the remote version of the branch into
            // their local branch.  For more details, see
            // [gitlet.merge()](#section-93).)
            Refs.Write("FETCH_HEAD", newHash + " branch " + branch + " of " + remoteUrl);

            // Report the result of the fetch.
            return
                (string.Format(
                     "From {0}\nCount {1}\n{2} -> {3}/{2}{4}\n",
                     remoteUrl,
                     remoteObjects.Length,
                     branch,
                     remote,
                     Core.Merge.IsAForceFetch(oldHash, newHash) ? " (forced)" : ""));
        }