示例#1
0
        /// <summary>
        /// Resolve a rev to a shortened commit sha1
        /// </summary>
        ///
        /// <param name="minimumLength">
        /// Minimum length of the shortened sha1, or <c>0</c> for Git to choose automatically
        /// </param>
        ///
        public GitShortSha1 GetShortCommitId(GitRev rev, int minimumLength = 0)
        {
            Guard.NotNull(rev, nameof(rev));

            if (minimumLength < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(minimumLength));
            }
            if (0 < minimumLength && minimumLength < 4)
            {
                throw new ArgumentOutOfRangeException(nameof(minimumLength));
            }

            var length = minimumLength == 0 ? "auto" : minimumLength.ToString();

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path,
                                                      "rev-parse", $"--short={length}", rev);

            if (r.ExitCode != 0)
            {
                throw new GitException("Resolve rev to short commit sha1 failed", r);
            }

            return(new GitShortSha1(r.StandardOutput.Trim()));
        }
        public void Captures_Output_Correctly()
        {
            var result = ProcessExtensions.ExecuteCaptured(true, true, null, TestExe);

            result.StandardOutput.ShouldBe(
                Lines(
                    "aaa",
                    "bbb",
                    "",
                    "ccc"));

            result.ErrorOutput.ShouldBe(
                Lines(
                    "ddd",
                    "eee",
                    "",
                    "fff"));


            result.CombinedOutput.Trim().Split(new[] { Environment.NewLine }, StringSplitOptions.None)
            .ShouldBe(
                new[] {
                "aaa",
                "bbb",
                "",
                "ccc",
                "ddd",
                "eee",
                "",
                "fff",
            },
                ignoreOrder: true);

            result.ExitCode.ShouldBe(0);
        }
示例#3
0
        /// <summary>
        /// Clone a Git repository
        /// </summary>
        ///
        public static GitRepository Clone(string parentPath, GitUrl url)
        {
            Guard.Required(parentPath, nameof(parentPath));
            if (!Directory.Exists(parentPath))
            {
                throw new ArgumentException("Parent path doesn't exist", nameof(parentPath));
            }
            Guard.NotNull(url, nameof(url));

            var directoryName = IOPath.GetFileName(url.AbsolutePath);

            if (directoryName.EndsWith(".git", StringComparison.OrdinalIgnoreCase))
            {
                directoryName = directoryName.Substring(0, directoryName.Length - 4);
            }

            var path = IOPath.Combine(parentPath, directoryName);

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", parentPath, "clone", url);

            if (r.ExitCode != 0)
            {
                throw new GitException("Cloning repository failed", r);
            }

            return(new GitRepository(path));
        }
        public void Passes_Arguments_Correctly()
        {
            var result = ProcessExtensions.ExecuteCaptured(true, true, null, TestExe, "a b c", "d", "\"e f\"");

            result.StandardOutput.ShouldContain("arg0: a b c");
            result.StandardOutput.ShouldContain("arg1: d");
            result.StandardOutput.ShouldContain("arg2: e f");
        }
示例#5
0
        /// <summary>
        /// Stage uncommitted changes
        /// </summary>
        ///
        public void StageChanges()
        {
            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "add", "-A");

            if (r.ExitCode != 0)
            {
                throw new GitException("Stage uncommitted changes failed", r);
            }
        }
示例#6
0
        /// <summary>
        /// Invoke the nugit.exe under test, for use by tests
        /// </summary>
        ///
        static void Nugit(GitRepository repo, string command, params string[] args)
        {
            var allArgs = new [] { command }.Concat(args).ToArray();
            var r = ProcessExtensions.ExecuteCaptured(true, true, repo.Path, nugitPath, allArgs);

            if (r.ExitCode != 0)
            {
                throw new Exception("nugit failed");
            }
        }
示例#7
0
        /// <summary>
        /// Delete a tag
        /// </summary>
        ///
        public void DeleteTag(GitRefNameComponent name)
        {
            Guard.NotNull(name, nameof(name));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "tag", "-d", name);

            if (r.ExitCode != 0)
            {
                throw new GitException("Delete tag failed", r);
            }
        }
示例#8
0
        /// <summary>
        /// Are there any uncommitted changes?
        /// </summary>
        ///
        /// <remarks>
        /// "Uncommitted changes" includes staged or unstaged changes of any kind.
        /// </remarks>
        ///
        /// <exception cref="GitException">
        /// The check for uncommitted changes failed
        /// </exception>
        ///
        public bool HasUncommittedChanges()
        {
            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "status", "--porcelain");

            if (r.ExitCode != 0)
            {
                throw new GitException("Uncommitted changes check failed", r);
            }

            return(r.CombinedOutput.Trim() != "");
        }
        public void Uses_Specified_WorkingDirectory()
        {
            var here = Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            var testWorkingDirectory = Path.Combine(here, "testworkingdirectory");

            Directory.CreateDirectory(testWorkingDirectory);
            var result =
                ProcessExtensions.ExecuteCaptured(true, true, testWorkingDirectory, TestExe, "workingdirectory");

            result.StandardOutput.Trim().ShouldBe(testWorkingDirectory);
        }
示例#10
0
        /// <summary>
        /// Commit staged changes
        /// </summary>
        ///
        public void Commit(string message)
        {
            Guard.Required(message, nameof(message));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "commit", "-m", message);

            if (r.ExitCode != 0)
            {
                throw new GitException("Commit failed", r);
            }
        }
示例#11
0
        /// <summary>
        /// Create a branch
        /// </summary>
        ///
        public void CreateBranch(GitRefNameComponent name, GitRev target)
        {
            Guard.NotNull(name, nameof(name));
            Guard.NotNull(target, nameof(target));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "branch", name, target);

            if (r.ExitCode != 0)
            {
                throw new GitException("Create branch failed", r);
            }
        }
示例#12
0
        /// <summary>
        /// Get a symbolic ref's target
        /// </summary>
        ///
        /// <returns>
        /// The name of the symbolic ref's target
        /// - OR -
        /// <c>null</c> if the ref is not symbolic
        /// - OR -
        /// <c>null</c> if the ref doesn't exist
        /// </returns>
        ///
        public GitFullRefName FindSymbolicRefTarget(GitFullRefName name)
        {
            Guard.NotNull(name, nameof(name));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "symbolic-ref", name);

            if (r.ExitCode != 0)
            {
                return(null);
            }

            return(new GitFullRefName(r.StandardOutput.Trim()));
        }
示例#13
0
        /// <summary>
        /// Get list of remote branches and the commit ids they point to
        /// </summary>
        ///
        public IEnumerable <GitRef> GetRemoteBranches()
        {
            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "ls-remote", "--heads");

            switch (r.ExitCode)
            {
            case 0:
                return(ParseRefLines(StringExtensions.SplitLines(r.StandardOutput)));

            default:
                throw new GitException("Get remote branches failed", r);
            }
        }
示例#14
0
        /// <summary>
        /// Resolve a rev to a commit sha1
        /// </summary>
        ///
        public GitSha1 GetCommitId(GitRev rev)
        {
            Guard.NotNull(rev, nameof(rev));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path,
                                                      "rev-parse", "-q", "--verify", $"{rev}^{{commit}}");

            if (r.ExitCode != 0)
            {
                throw new GitException("Resolve rev to commit sha1 failed", r);
            }

            return(new GitSha1(r.StandardOutput.Trim()));
        }
示例#15
0
        /// <summary>
        /// Get list of tags and the commit ids they point to
        /// </summary>
        ///
        public IEnumerable <GitRef> GetTags()
        {
            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path,
                                                      "show-ref", "--tags", "-d");

            switch (r.ExitCode)
            {
            case 0:
            case 1:
                return(ParseRefLines(StringExtensions.SplitLines(r.StandardOutput)));

            default:
                throw new GitException("Get tags failed", r);
            }
        }
示例#16
0
        /// <summary>
        /// Check out a particular commit
        /// </summary>
        ///
        /// <exception cref="InvalidOperationException">
        /// The repository has uncommitted changes
        /// </exception>
        ///
        /// <exception cref="GitException">
        /// The checkout operation failed
        /// </exception>
        ///
        public void Checkout(GitRev rev)
        {
            Guard.NotNull(rev, nameof(rev));

            if (HasUncommittedChanges())
            {
                throw new InvalidOperationException("Repository contains uncommitted changes");
            }

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "checkout", rev);

            if (r.ExitCode != 0)
            {
                throw new GitException("Checkout failed", r);
            }
        }
示例#17
0
        /// <summary>
        /// Get the name of the currently-checked-out branch
        /// </summary>
        ///
        /// <returns>
        /// The name of the currently-checked out branch
        /// - OR -
        /// <c>null</c> if no branch is checked out
        /// </returns>
        ///
        public GitRefNameComponent GetBranch()
        {
            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "rev-parse", "--abbrev-ref", "HEAD");

            if (r.ExitCode != 0)
            {
                throw new GitException("Get current branch failed", r);
            }

            var branchName = r.StandardOutput.Trim();

            if (branchName == "HEAD")
            {
                return(null);
            }

            return(new GitRefNameComponent(branchName));
        }
示例#18
0
        /// <summary>
        /// Determine whether a file or directory within the repository is .gitignore'd
        /// </summary>
        ///
        public bool IsIgnored(string path)
        {
            Guard.NotNull(path, nameof(path));
            Guard.NotWhiteSpaceOnly(path, nameof(path));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", Path, "check-ignore", "-q", path);

            switch (r.ExitCode)
            {
            case 0:
                return(true);

            case 1:
                return(false);

            default:
                throw new GitException("check-ignore failed", r);
            }
        }
示例#19
0
        /// <summary>
        /// Is one commit the ancestor of another?
        /// </summary>
        ///
        public bool IsAncestor(GitRev ancestor, GitRev descendent)
        {
            Guard.NotNull(ancestor, nameof(ancestor));
            Guard.NotNull(descendent, nameof(descendent));

            var r = ProcessExtensions.ExecuteCaptured(false, false, null,
                                                      "git", "-C", Path, "merge-base", "--is-ancestor", ancestor, descendent);

            switch (r.ExitCode)
            {
            case 0:
                return(true);

            case 1:
                return(false);

            default:
                throw new GitException("merge-base --is-ancestor failed", r);
            }
        }
示例#20
0
        /// <summary>
        /// Push branches or tags to a remote
        /// </summary>
        ///
        /// <param name="refs">
        /// Names of branches and/or tags to push
        /// </param>
        ///
        /// <param name="remote">
        /// Name of remote (default "origin")
        /// </param>
        ///
        /// <param name="dryRun">
        /// Don't actually do anything, just show what would be done
        /// </param>
        ///
        /// <param name="echoOutput">
        /// Echo Git command output as it runs
        /// </param>
        ///
        /// <returns>
        /// Git command output
        /// </returns>
        ///
        public string Push(
            IEnumerable <GitFullRefName> refs,
            string remote   = "origin",
            bool dryRun     = false,
            bool echoOutput = false)
        {
            Guard.NotNull(refs, nameof(refs));
            Guard.NotNull(remote, nameof(remote));
            Guard.NotWhiteSpaceOnly(remote, nameof(remote));

            if (!refs.Any())
            {
                return("");
            }

            var args = new List <string>()
            {
                "-C", Path, "push", "--atomic"
            };

            if (dryRun)
            {
                args.Add("--dry-run");
            }
            args.Add(remote);
            args.AddRange(refs.Select(r => r.ToString()));

            var result = ProcessExtensions.ExecuteCaptured(false, echoOutput, null, "git", args.ToArray());

            if (result.ExitCode != 0)
            {
                throw new GitException("Push failed", result);
            }

            return(result.CombinedOutput);
        }
示例#21
0
        /// <summary>
        /// Initialise a new Git repository
        /// </summary>
        ///
        /// <remarks>
        /// If the specified <paramref name="path"/> doesn't exist, it is created
        /// </remarks>
        ///
        /// <param name="path">
        /// Path to new repository
        /// </param>
        ///
        /// <returns>
        /// The newly-initialised repository
        /// </returns>
        ///
        /// <exception cref="InvalidOperationException">
        /// The specified <paramref name="path"/> is already a Git repository
        /// </exception>
        ///
        public static GitRepository Init(string path)
        {
            Guard.Required(path, nameof(path));
            path = IOPath.GetFullPath(path);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            if (IsRepository(path))
            {
                throw new InvalidOperationException("Path is already a Git repository");
            }

            var r = ProcessExtensions.ExecuteCaptured(false, false, null, "git", "-C", path, "init");

            if (r.ExitCode != 0)
            {
                throw new GitException("Initialising repository failed", r);
            }

            return(new GitRepository(path));
        }
 public void Non_Existent_WorkingDirectory_Fails()
 {
     Should.Throw <ArgumentException>(() =>
                                      ProcessExtensions.ExecuteCaptured(true, true, "C:\\does\\not\\exist", TestExe, "workingdirectory"));
 }
        public void Captures_CommandLine()
        {
            var result = ProcessExtensions.ExecuteCaptured(true, true, null, TestExe);

            result.CommandLine.ShouldNotBeNullOrWhiteSpace();
        }
        public void Uses_Current_WorkingDirectory_By_Default()
        {
            var result = ProcessExtensions.ExecuteCaptured(true, true, null, TestExe, "workingdirectory");

            result.StandardOutput.Trim().ShouldBe(Path.GetFullPath(Environment.CurrentDirectory));
        }
 public void Relative_WorkingDirectory_Fails()
 {
     Should.Throw <ArgumentException>(() =>
                                      ProcessExtensions.ExecuteCaptured(true, true, "relative\\path", TestExe, "workingdirectory"));
 }