public void GivenARemoteGitRepositoryWithCommitsAndBranches_ThenClonedLocalShouldMatchRemoteVersion() { using (var fixture = new RemoteRepositoryFixture( path => { Repository.Init(path); Console.WriteLine("Created git repository at '{0}'", path); var repo = new Repository(path); repo.MakeCommits(5); repo.CreateBranch("develop"); repo.CreateBranch("release-1.0"); repo.Checkout("release-1.0"); repo.MakeCommits(5); return repo; })) { GitRepositoryHelper.NormalizeGitDirectory(fixture.LocalRepositoryFixture.RepositoryPath, new AuthenticationInfo(), noFetch: false, currentBranch: string.Empty); fixture.AssertFullSemver("1.0.0-beta.1+5"); fixture.AssertFullSemver("1.0.0-beta.1+5", fixture.LocalRepositoryFixture.Repository); } }
public void GivenARemoteGitRepositoryWithCommitsAndBranches_ThenClonedLocalShouldMatchRemoteVersion() { using (var fixture = new RemoteRepositoryFixture( path => { Repository.Init(path); Console.WriteLine("Created git repository at '{0}'", path); var repo = new Repository(path); repo.MakeCommits(5); repo.CreateBranch("develop"); repo.CreateBranch("release-1.0"); repo.Checkout("release-1.0"); repo.MakeCommits(5); return repo; }, new Config())) { fixture.AssertFullSemver("1.0.0-beta.1+5"); fixture.AssertFullSemver("1.0.0-beta.1+5", fixture.LocalRepository); } }
public void CanFastForwardRepos(bool shouldMergeOccurInDetachedHeadState) { const string firstBranchFileName = "first branch file.txt"; const string sharedBranchFileName = "first+second branch file.txt"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { // Reset the index and the working tree. repo.Reset(ResetMode.Hard); // Clean the working directory. repo.RemoveUntrackedFiles(); var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); if (shouldMergeOccurInDetachedHeadState) { // Detaches HEAD repo.Checkout(secondBranch.Tip); } else { secondBranch.Checkout(); } Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.FastForward, mergeResult.Status); Assert.Equal(repo.Branches["FirstBranch"].Tip, mergeResult.Commit); Assert.Equal(repo.Branches["FirstBranch"].Tip, repo.Head.Tip); Assert.Equal(repo.Head.Tip, mergeResult.Commit); Assert.Equal(0, repo.Index.RetrieveStatus().Count()); Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); if (!shouldMergeOccurInDetachedHeadState) { // Ensure HEAD is still attached and points to SecondBranch Assert.Equal(repo.Refs.Head.TargetIdentifier, secondBranch.CanonicalName); } } }
public void CanFollowFirstParent() { string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { var branch = repo.CreateBranch("branch"); // Make an earlier tag on master repo.Commit("A", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true }); repo.ApplyTag("firstParentTag"); // Make a later tag on branch Commands.Checkout(repo, branch); repo.Commit("B", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true }); repo.ApplyTag("mostRecentTag"); Commands.Checkout(repo, "master"); repo.Commit("C", Constants.Signature, Constants.Signature, new CommitOptions { AllowEmptyCommit = true }); repo.Merge(branch, Constants.Signature, new MergeOptions() { FastForwardStrategy = FastForwardStrategy.NoFastForward }); // With OnlyFollowFirstParent = false, the most recent tag reachable should be returned Assert.Equal("mostRecentTag-3-gf17be71", repo.Describe(repo.Head.Tip, new DescribeOptions { OnlyFollowFirstParent = false, Strategy = DescribeStrategy.Tags })); // With OnlyFollowFirstParent = true, the most recent tag on the current branch should be returned Assert.Equal("firstParentTag-2-gf17be71", repo.Describe(repo.Head.Tip, new DescribeOptions { OnlyFollowFirstParent = true, Strategy = DescribeStrategy.Tags })); } }
static void CreateFakePullRequest(string repoPath, string issueNumber) { // Fake an upstream repository as it would appear on GitHub // will pull requests stored under the refs/pull/ namespace using (var repo = new Repository(repoPath)) { var branch = repo.CreateBranch("temp", repo.Branches["develop"].Tip); branch.Checkout(); AddOneCommitToHead(repo, "code"); AddOneCommitToHead(repo, "code"); var c = repo.Head.Tip; repo.Refs.Add(string.Format("refs/pull/{0}/head", issueNumber), c.Id); var sign = SignatureBuilder.SignatureNow(); var m = repo.ObjectDatabase.CreateCommit( sign, sign, string.Format("Merge pull request #{0} from nulltoken/ntk/fix/{0}", issueNumber) , c.Tree, new[] { repo.Branches["develop"].Tip, c }, true); repo.Refs.Add(string.Format("refs/pull/{0}/merge", issueNumber), m.Id); repo.Checkout("develop"); repo.Branches.Remove("temp"); } }
public void CanCancelCheckoutThroughNotifyCallback() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { string relativePath = "a.txt"; Touch(repo.Info.WorkingDirectory, relativePath, "Hello\n"); repo.Index.Stage(relativePath); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); // Create 2nd branch repo.CreateBranch("branch2"); // Update file in main Touch(repo.Info.WorkingDirectory, relativePath, "Hello from master!\n"); repo.Index.Stage(relativePath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); // Checkout branch2 repo.Checkout("branch2"); // Update the context of a.txt - a.txt will then conflict between branch2 and master. Touch(repo.Info.WorkingDirectory, relativePath, "Hello From branch2!\n"); // Verify that we get called for the notify conflict cb string conflictPath = string.Empty; CheckoutNotificationOptions checkoutNotifications = new CheckoutNotificationOptions((path, flags) => { conflictPath = path; return false; }, CheckoutNotifyFlags.Conflict); Assert.Throws<UserCancelledException>(() => repo.Checkout("master", CheckoutModifiers.None, null, checkoutNotifications)); Assert.Equal(relativePath, conflictPath); } }
public void CanCommitALittleBit() { SelfCleaningDirectory scd = BuildSelfCleaningDirectory(); string dir = Repository.Init(scd.DirectoryPath); Path.IsPathRooted(dir).ShouldBeTrue(); Directory.Exists(dir).ShouldBeTrue(); using (var repo = new Repository(dir)) { const string relativeFilepath = "new.txt"; string filePath = Path.Combine(repo.Info.WorkingDirectory, relativeFilepath); File.WriteAllText(filePath, "null"); repo.Index.Stage(relativeFilepath); File.AppendAllText(filePath, "token\n"); repo.Index.Stage(relativeFilepath); repo.Head[relativeFilepath].ShouldBeNull(); var author = new Signature("Author N. Ame", "*****@*****.**", DateTimeOffset.Now.AddSeconds(-10)); Commit commit = repo.Commit("Initial egotistic commit", author, author); AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n"); AssertBlobContent(commit[relativeFilepath], "nulltoken\n"); commit.Parents.Count().ShouldEqual(0); repo.Info.IsEmpty.ShouldBeFalse(); File.WriteAllText(filePath, "nulltoken commits!\n"); repo.Index.Stage(relativeFilepath); var author2 = new Signature(author.Name, author.Email, author.When.AddSeconds(5)); Commit commit2 = repo.Commit("Are you trying to fork me?", author2, author2); AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n"); AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n"); commit2.Parents.Count().ShouldEqual(1); commit2.Parents.First().Id.ShouldEqual(commit.Id); Branch firstCommitBranch = repo.CreateBranch("davidfowl-rules", commit.Id.Sha); //TODO: This cries for a shortcut method :-/ repo.Branches.Checkout(firstCommitBranch.Name); //TODO: This cries for a shortcut method :-/ File.WriteAllText(filePath, "davidfowl commits!\n"); var author3 = new Signature("David Fowler", "*****@*****.**", author.When.AddSeconds(2)); repo.Index.Stage(relativeFilepath); Commit commit3 = repo.Commit("I'm going to branch you backwards in time!", author3, author3); AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n"); AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n"); commit3.Parents.Count().ShouldEqual(1); commit3.Parents.First().Id.ShouldEqual(commit.Id); AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n"); } }
public void CanCreateBranchFromExplicitHead() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "unit_test"; Branch newBranch = repo.CreateBranch(name, "HEAD"); newBranch.ShouldNotBeNull(); newBranch.Tip.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345"); } }
public void CherryPickWithConflictDoesNotCommit() { const string firstBranchFileName = "first branch file.txt"; const string secondBranchFileName = "second branch file.txt"; const string sharedBranchFileName = "first+second branch file.txt"; string path = SandboxStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); repo.Checkout(firstBranch); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); AddFileCommitToRepo(repo, sharedBranchFileName, "The first branches comment"); // Change file in first branch repo.Checkout(secondBranch); // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit). AddFileCommitToRepo(repo, secondBranchFileName); AddFileCommitToRepo(repo, sharedBranchFileName, "The second branches comment"); // Change file in second branch CherryPickResult cherryPickResult = repo.CherryPick(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(CherryPickStatus.Conflicts, cherryPickResult.Status); Assert.Null(cherryPickResult.Commit); Assert.Equal(1, repo.Index.Conflicts.Count()); var conflict = repo.Index.Conflicts.First(); var changes = repo.Diff.Compare(repo.Lookup<Blob>(conflict.Theirs.Id), repo.Lookup<Blob>(conflict.Ours.Id)); Assert.False(changes.IsBinaryComparison); } }
public void CanCreateBranchFromImplicitHead() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "unit_test"; Branch newBranch = repo.CreateBranch(name); newBranch.ShouldNotBeNull(); newBranch.Name.ShouldEqual(name); newBranch.CanonicalName.ShouldEqual("refs/heads/" + name); newBranch.IsCurrentRepositoryHead.ShouldBeFalse(); newBranch.Tip.ShouldNotBeNull(); newBranch.Tip.Sha.ShouldEqual("4c062a6361ae6959e06292c1fa5e2822d9c96345"); repo.Branches.SingleOrDefault(p => p.Name == name).ShouldNotBeNull(); } }
public void CanCreateBranch() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "unit_test"; Branch newBranch = repo.CreateBranch(name, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); newBranch.ShouldNotBeNull(); newBranch.Name.ShouldEqual(name); newBranch.CanonicalName.ShouldEqual("refs/heads/" + name); newBranch.Tip.ShouldNotBeNull(); newBranch.Tip.Sha.ShouldEqual("be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); repo.Branches.SingleOrDefault(p => p.Name == name).ShouldNotBeNull(); repo.Branches.Delete(newBranch.Name); } }
public void AppendingToReflogDependsOnCoreLogAllRefUpdatesSetting(bool isBare, bool? setting, bool expectAppend) { var repoPath = InitNewRepository(isBare); using (var repo = new Repository(repoPath)) { if (setting != null) { EnableRefLog(repo, setting.Value); } var blob = repo.ObjectDatabase.CreateBlob(Stream.Null); var tree = repo.ObjectDatabase.CreateTree(new TreeDefinition().Add("yoink", blob, Mode.NonExecutableFile)); var commit = repo.ObjectDatabase.CreateCommit(Constants.Signature, Constants.Signature, "yoink", tree, Enumerable.Empty<Commit>(), false); var branch = repo.CreateBranch("yoink", commit); var log = repo.Refs.Log(branch.CanonicalName); Assert.Equal(expectAppend ? 1 : 0, log.Count()); } }
public void CorrectlyEncodesAndDecodesInput() { const string decodedInput = "This is a substitution cipher"; const string encodedInput = "Guvf vf n fhofgvghgvba pvcure"; var attributes = new List<FilterAttributeEntry> { new FilterAttributeEntry("rot13") }; var filter = new SubstitutionCipherFilter("cipher-filter", attributes); var filterRegistration = GlobalSettings.RegisterFilter(filter); string repoPath = InitNewRepository(); string fileName = Guid.NewGuid() + ".rot13"; using (var repo = new Repository(repoPath)) { CreateConfigurationWithDummyUser(repo, Constants.Identity); CreateAttributesFile(repo, "*.rot13 filter=rot13"); var blob = CommitOnBranchAndReturnDatabaseBlob(repo, fileName, decodedInput); var textDetected = blob.GetContentText(); Assert.Equal(encodedInput, textDetected); Assert.Equal(1, filter.CleanCalledCount); Assert.Equal(0, filter.SmudgeCalledCount); var branch = repo.CreateBranch("delete-files"); Commands.Checkout(repo, branch.FriendlyName); DeleteFile(repo, fileName); Commands.Checkout(repo, "master"); var fileContents = ReadTextFromFile(repo, fileName); Assert.Equal(1, filter.SmudgeCalledCount); Assert.Equal(decodedInput, fileContents); } GlobalSettings.DeregisterFilter(filterRegistration); }
public void GivenARemoteWithATagOnMaster_AndAPullRequestWithTwoCommits_AndBuildIsRunningInTeamCity_VersionIsCalculatedProperly(string pullRequestRef) { using (var fixture = new EmptyRepositoryFixture()) { var remoteRepositoryPath = PathHelper.GetTempPath(); Repository.Init(remoteRepositoryPath); using (var remoteRepository = new Repository(remoteRepositoryPath)) { remoteRepository.Config.Set("user.name", "Test"); remoteRepository.Config.Set("user.email", "*****@*****.**"); fixture.Repository.Network.Remotes.Add("origin", remoteRepositoryPath); Console.WriteLine("Created git repository at {0}", remoteRepositoryPath); remoteRepository.MakeATaggedCommit("1.0.3"); var branch = remoteRepository.CreateBranch("FeatureBranch"); remoteRepository.Checkout(branch); remoteRepository.MakeCommits(2); remoteRepository.Checkout(remoteRepository.Head.Tip.Sha); //Emulate merge commit var mergeCommitSha = remoteRepository.MakeACommit().Sha; remoteRepository.Checkout("master"); // HEAD cannot be pointing at the merge commit remoteRepository.Refs.Add(pullRequestRef, new ObjectId(mergeCommitSha)); // Checkout PR commit Commands.Fetch((Repository)fixture.Repository, "origin", new string[0], new FetchOptions(), null); fixture.Repository.Checkout(mergeCommitSha); } var result = GitVersionHelper.ExecuteIn(fixture.RepositoryPath, isTeamCity: true); result.ExitCode.ShouldBe(0); result.OutputVariables.FullSemVer.ShouldBe("1.0.4-PullRequest0005.3"); // Cleanup repository files DirectoryHelper.DeleteDirectory(remoteRepositoryPath); } }
public void CanFollowBranches(string specificRepoPath) { var repoPath = specificRepoPath ?? CreateEmptyRepository(); var path = "Test.txt"; var dummy = new string('a', 1024); using (var repo = new Repository(repoPath)) { var master0 = AddCommitToOdb(repo, "0. Initial commit for this test", path, "Before merge", dummy); var fix1 = AddCommitToOdb(repo, "1. Changed on fix", path, "Change on fix branch", dummy, master0); var master2 = AddCommitToOdb(repo, "2. Changed on master", path, "Independent change on master branch", dummy, master0); path = "New" + path; var fix3 = AddCommitToOdb(repo, "3. Changed and renamed on fix", path, "Another change on fix branch", dummy, fix1); var master4 = AddCommitToOdb(repo, "4. Changed and renamed on master", path, "Another independent change on master branch", dummy, master2); var master5 = AddCommitToOdb(repo, "5. Merged fix into master", path, "Manual resolution of merge conflict", dummy, master4, fix3); var master6 = AddCommitToOdb(repo, "6. Changed on master", path, "Change after merge", dummy, master5); var nextfix7 = AddCommitToOdb(repo, "7. Changed on next-fix", path, "Change on next-fix branch", dummy, master6); var master8 = AddCommitToOdb(repo, "8. Changed on master", path, "Some arbitrary change on master branch", dummy, master6); var master9 = AddCommitToOdb(repo, "9. Merged next-fix into master", path, "Another manual resolution of merge conflict", dummy, master8, nextfix7); var master10 = AddCommitToOdb(repo, "10. Changed on master", path, "A change on master after merging", dummy, master9); repo.CreateBranch("master", master10); Commands.Checkout(repo, "master", new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force }); // Test --date-order. var timeHistory = repo.Commits.QueryBy(path, new CommitFilter { SortBy = CommitSortStrategies.Time }); var timeCommits = new List<Commit> { master10, // master master8, // master nextfix7, // next-fix master6, // master master4, // master fix3, // fix master2, // master fix1, // fix master0 // master (initial commit) }; Assert.Equal(timeCommits, timeHistory.Select(e => e.Commit)); // Test --topo-order. var topoHistory = repo.Commits.QueryBy(path, new CommitFilter { SortBy = CommitSortStrategies.Topological }); var topoCommits = new List<Commit> { master10, // master nextfix7, // next-fix master8, // master master6, // master fix3, // fix fix1, // fix master4, // master master2, // master master0 // master (initial commit) }; Assert.Equal(topoCommits, topoHistory.Select(e => e.Commit)); } }
public void CreateBranch(string branchName) { _repo.Checkout(_repo.CreateBranch(branchName)); }
public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, string expectedNotificationPath, bool isDirectory) { if (isDirectory) { expectedNotificationPath = expectedNotificationPath + Path.DirectorySeparatorChar; } string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); string relativePathUpdated = "updated.txt"; Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text A"); repo.Stage(relativePathUpdated); repo.Commit("Commit initial update file", Constants.Signature, Constants.Signature); // Create conflicting change string relativePathConflict = "conflict.txt"; Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text A"); repo.Stage(relativePathConflict); repo.Commit("Initial commit of conflict.txt and update.txt", Constants.Signature, Constants.Signature); // Create another branch repo.CreateBranch("newbranch"); // Make an edit to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text BB"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text BB"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on master branch", Constants.Signature, Constants.Signature); // Checkout other branch repo.Checkout("newbranch"); // Make alternate edits to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text CCC"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text CCC"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on newbranch", Constants.Signature, Constants.Signature); // make conflicting change to conflict.txt Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text DDDD"); repo.Stage(relativePathConflict); // Create ignored change string relativePathIgnore = Path.Combine("bin", "ignored.txt"); Touch(repo.Info.WorkingDirectory, relativePathIgnore, "ignored file"); // Create untracked change string relativePathUntracked = "untracked.txt"; Touch(repo.Info.WorkingDirectory, relativePathUntracked, "untracked file"); bool wasCalled = false; string actualNotificationPath = string.Empty; CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; CheckoutOptions options = new CheckoutOptions() { OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return true; }, CheckoutNotifyFlags = notifyFlags, }; Assert.Throws<MergeConflictException>(() => repo.Checkout("master", options)); Assert.True(wasCalled); Assert.Equal(expectedNotificationPath, actualNotificationPath); Assert.Equal(notifyFlags, actualNotifyFlags); } }
/// <summary> /// Adds the standard .NET targets to the build. /// </summary> /// <param name="build">The build to which to add targets.</param> /// <param name="settings">The build settings.</param> public static void AddDotNetTargets(this BuildApp build, DotNetBuildSettings settings = null) { settings = settings ?? new DotNetBuildSettings(); var buildOptions = settings.BuildOptions ?? (settings.BuildOptions = new DotNetBuildOptions()); var configurationOption = buildOptions.ConfigurationOption ?? (buildOptions.ConfigurationOption = build.AddOption("-c|--configuration <name>", "The configuration to build (default Release)", "Release")); var platformOption = buildOptions.PlatformOption ?? (buildOptions.PlatformOption = build.AddOption("-p|--platform <name>", "The solution platform to build")); var versionSuffixOption = buildOptions.VersionSuffixOption ?? (buildOptions.VersionSuffixOption = build.AddOption("--version-suffix <suffix>", "Generates a prerelease package")); var nugetOutputOption = buildOptions.NuGetOutputOption ?? (buildOptions.NuGetOutputOption = build.AddOption("--nuget-output <path>", "Directory for generated package (default release)", "release")); var triggerOption = buildOptions.TriggerOption ?? (buildOptions.TriggerOption = build.AddOption("--trigger <name>", "The git branch or tag that triggered the build")); var buildNumberOption = buildOptions.BuildNumberOption ?? (buildOptions.BuildNumberOption = build.AddOption("--build-number <number>", "The automated build number")); var solutionName = settings.SolutionName; var nugetSource = settings.NuGetSource ?? "https://api.nuget.org/v3/index.json"; var msbuildSettings = settings.MSBuildSettings; var dotNetTools = settings.DotNetTools ?? new DotNetTools(Path.Combine("tools", "bin")); var sourceLinkVersion = settings.SourceLinkToolVersion ?? "3.1.1"; var xmlDocMarkdownVersion = settings.DocsSettings?.ToolVersion ?? "1.5.1"; var packageDiffVersion = settings.PackageDiffToolVersion ?? "0.2.1"; var packagePaths = new List <string>(); bool hasBadPackageVersion = false; build.Target("clean") .Describe("Deletes all build output") .Does(() => { foreach (var directory in FindDirectories("{src,tests}/**/{bin,obj}", "tools/bin", "release")) { Directory.Delete(directory, recursive: true); } var extraProperties = getExtraProperties("clean"); if (msbuildSettings == null) { RunDotNet(new[] { "clean", solutionName, "-c", configurationOption.Value, getPlatformArg(), "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, "-t:Clean", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("restore") .Describe("Restores NuGet packages") .Does(() => { var extraProperties = getExtraProperties("restore"); if (msbuildSettings == null) { RunDotNet(new[] { "restore", solutionName, getPlatformArg(), "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, "-t:Restore", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("build") .DependsOn("restore") .Describe("Builds the solution") .Does(() => { var buildNumberArg = buildNumberOption.Value == null ? null : $"-p:BuildNumber={buildNumberOption.Value}"; var extraProperties = getExtraProperties("build"); if (msbuildSettings == null) { RunDotNet(new[] { "build", solutionName, "-c", configurationOption.Value, getPlatformArg(), buildNumberArg, "--no-restore", "--verbosity", "normal", getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, $"-p:Configuration={configurationOption.Value}", getPlatformArg(), buildNumberArg, "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("test") .DependsOn("build") .Describe("Runs the unit tests") .Does(() => { var extraProperties = getExtraProperties("test"); var findTestAssemblies = settings.TestSettings?.FindTestAssemblies; if (findTestAssemblies != null) { foreach (var testAssembly in findTestAssemblies()) { RunDotNet(new AppRunnerSettings { Arguments = new[] { "vstest", Path.GetFileName(testAssembly) }.Concat(extraProperties), WorkingDirectory = Path.GetDirectoryName(testAssembly) }); } } else { RunDotNet(new[] { "test", solutionName, "-c", configurationOption.Value, getPlatformArg(), "--no-build", getMaxCpuCountArg() }.Concat(extraProperties)); } }); build.Target("package") .DependsOn("test") .Describe("Builds NuGet packages") .Does(() => { string versionSuffix = versionSuffixOption.Value; string trigger = triggerOption.Value; if (versionSuffix == null && trigger != null) { var group = s_triggerRegex.Match(trigger).Groups["suffix"]; if (group.Success) { versionSuffix = group.ToString(); } } var nugetOutputPath = Path.GetFullPath(nugetOutputOption.Value); var tempOutputPath = Path.Combine(nugetOutputPath, $"temp_{Guid.NewGuid():N}"); var extraProperties = getExtraProperties("package"); if (msbuildSettings == null) { RunDotNet(new[] { "pack", solutionName, "-c", configurationOption.Value, getPlatformArg(), "--no-build", "--output", tempOutputPath, versionSuffix != null ? "--version-suffix" : null, versionSuffix, getMaxCpuCountArg() }.Concat(extraProperties)); } else { runMSBuild(new[] { solutionName, "-t:Pack", $"-p:Configuration={configurationOption.Value}", getPlatformArg(), "-p:NoBuild=true", $"-p:PackageOutputPath={tempOutputPath}", versionSuffix != null ? $"-p:VersionSuffix={versionSuffix}" : null, "-v:normal", getMaxCpuCountArg() }.Concat(extraProperties)); } var tempPackagePaths = FindFilesFrom(tempOutputPath, "*.nupkg"); foreach (var tempPackagePath in tempPackagePaths) { var packagePath = Path.Combine(nugetOutputPath, Path.GetFileName(tempPackagePath)); if (File.Exists(packagePath)) { File.Delete(packagePath); } File.Move(tempPackagePath, packagePath); packagePaths.Add(packagePath); } Directory.Delete(tempOutputPath); if (packagePaths.Count == 0) { throw new ApplicationException("No NuGet packages created."); } var projectUsesSemVer = settings.ProjectUsesSemVer; foreach (var packagePath in packagePaths) { var packageInfo = GetPackageInfo(packagePath); if (projectUsesSemVer == null || projectUsesSemVer(packageInfo.Name)) { int exitCode = RunApp(dotNetTools.GetToolPath($"Faithlife.PackageDiffTool.Tool/{packageDiffVersion}", "packagediff"), new AppRunnerSettings { Arguments = new[] { "--verifyversion", "--verbose", packagePath }, IsExitCodeSuccess = x => x <= 2, // don't fail on crash }); hasBadPackageVersion = exitCode == 2; } } }); build.Target("publish") .Describe("Publishes NuGet packages and documentation") .DependsOn("clean", "package") .Does(() => { if (packagePaths.Count == 0) { throw new ApplicationException("No NuGet packages found."); } var trigger = triggerOption.Value; if (trigger == null) { throw new ApplicationException("--trigger option required."); } bool shouldPublishPackages = trigger == "publish-package" || trigger == "publish-packages" || trigger == "publish-all"; bool shouldPublishDocs = trigger == "publish-docs" || trigger == "publish-all"; var triggerMatch = s_triggerRegex.Match(trigger); if (triggerMatch.Success) { var triggerName = triggerMatch.Groups["name"].Value; var triggerVersion = triggerMatch.Groups["version"].Value; if (triggerName.Length == 0) { var mismatches = packagePaths.Where(x => GetPackageInfo(x).Version != triggerVersion).ToList(); if (mismatches.Count != 0) { throw new ApplicationException($"Trigger '{trigger}' doesn't match package version: {string.Join(", ", mismatches.Select(Path.GetFileName))}"); } } else { var matches = packagePaths.Where(x => $".{GetPackageInfo(x).Name}".EndsWith($".{triggerName}", StringComparison.OrdinalIgnoreCase)).ToList(); if (matches.Count == 0) { throw new ApplicationException($"Trigger '{trigger}' does not match any packages: {string.Join(", ", packagePaths.Select(Path.GetFileName))}"); } if (matches.Count > 1) { throw new ApplicationException($"Trigger '{trigger}' matches multiple package(s): {string.Join(", ", matches.Select(Path.GetFileName))}"); } if (GetPackageInfo(matches[0]).Version != triggerVersion) { throw new ApplicationException($"Trigger '{trigger}' doesn't match package version: {Path.GetFileName(matches[0])}"); } packagePaths = matches; } shouldPublishPackages = true; shouldPublishDocs = !triggerMatch.Groups["suffix"].Success; } if (shouldPublishPackages && hasBadPackageVersion) { throw new ApplicationException("Use suggested package version to publish."); } if (shouldPublishPackages || shouldPublishDocs) { var docsSettings = settings.DocsSettings; bool shouldPushDocs = false; string cloneDirectory = null; string repoDirectory = null; string gitBranchName = null; Credentials provideCredentials(string url, string usernameFromUrl, SupportedCredentialTypes types) => new UsernamePasswordCredentials { Username = docsSettings.GitLogin.Username ?? throw new ApplicationException("GitLogin has a null Username."), Password = docsSettings.GitLogin.Password ?? throw new ApplicationException("GitLogin has a null Password."), }; if (shouldPublishDocs && docsSettings != null) { if (docsSettings.GitLogin == null || docsSettings.GitAuthor == null) { throw new ApplicationException("GitLogin and GitAuthor must be set on DocsSettings."); } var gitRepositoryUrl = docsSettings.GitRepositoryUrl; gitBranchName = docsSettings.GitBranchName; if (gitRepositoryUrl != null) { cloneDirectory = "docs_repo_" + Path.GetRandomFileName(); Repository.Clone(sourceUrl: gitRepositoryUrl, workdirPath: cloneDirectory, options: new CloneOptions { BranchName = gitBranchName, CredentialsProvider = provideCredentials }); repoDirectory = cloneDirectory; } else { repoDirectory = "."; } using (var repository = new Repository(repoDirectory)) { if (gitRepositoryUrl != null) { if (gitBranchName == null) { gitBranchName = repository.Head.FriendlyName; } } else if (gitBranchName != null) { if (gitBranchName != repository.Head.FriendlyName) { var branch = repository.Branches[gitBranchName] ?? repository.CreateBranch(gitBranchName); Commands.Checkout(repository, branch); } } else { var branch = repository.Branches.FirstOrDefault(x => x.IsCurrentRepositoryHead); if (branch == null) { var autoBranchName = Environment.GetEnvironmentVariable("APPVEYOR_REPO_BRANCH"); if (autoBranchName == null) { throw new ArgumentException("Could not determine repository branch."); } branch = repository.Branches[autoBranchName] ?? repository.CreateBranch(autoBranchName); Commands.Checkout(repository, branch); } gitBranchName = branch.FriendlyName; } foreach (var projectName in packagePaths.Select(x => GetPackageInfo(x).Name)) { string findAssembly(string name) => FindFiles($"tools/XmlDocTarget/bin/**/{name}.dll").OrderByDescending(File.GetLastWriteTime).FirstOrDefault() ?? FindFiles($"src/{name}/bin/**/{name}.dll").OrderByDescending(File.GetLastWriteTime).FirstOrDefault(); var assemblyPath = (docsSettings.FindAssembly ?? findAssembly)(projectName); if (assemblyPath != null) { RunApp(dotNetTools.GetToolPath($"xmldocmd/{xmlDocMarkdownVersion}"), assemblyPath, Path.Combine(repoDirectory, docsSettings.TargetDirectory ?? "docs"), "--source", $"{docsSettings.SourceCodeUrl}/{projectName}", "--newline", "lf", "--clean"); } else { Console.WriteLine($"Documentation not generated for {projectName}; assembly not found."); } } shouldPushDocs = repository.RetrieveStatus().IsDirty; } } if (shouldPublishPackages) { var projectUsesSourceLink = settings.ProjectUsesSourceLink; foreach (var packagePath in packagePaths) { if (projectUsesSourceLink == null || projectUsesSourceLink(GetPackageInfo(packagePath).Name)) { RunApp(dotNetTools.GetToolPath($"sourcelink/{sourceLinkVersion}"), "test", packagePath); } } var nugetApiKey = settings.NuGetApiKey; if (string.IsNullOrEmpty(nugetApiKey)) { throw new ApplicationException("NuGetApiKey required to publish."); } foreach (var packagePath in packagePaths) { RunDotNet("nuget", "push", packagePath, "--source", nugetSource, "--api-key", nugetApiKey); } } if (shouldPushDocs) { using (var repository = new Repository(repoDirectory)) { Console.WriteLine("Publishing documentation changes."); Commands.Stage(repository, "*"); var author = new Signature(docsSettings.GitAuthor.Name, docsSettings.GitAuthor.Email, DateTimeOffset.Now); repository.Commit("Documentation updated.", author, author, new CommitOptions()); repository.Network.Push(repository.Network.Remotes["origin"], $"refs/heads/{gitBranchName}", new PushOptions { CredentialsProvider = provideCredentials }); } } if (cloneDirectory != null) { // delete the cloned directory foreach (var fileInfo in FindFiles(cloneDirectory, "**").Select(x => new FileInfo(x)).Where(x => x.IsReadOnly)) { fileInfo.IsReadOnly = false; } Directory.Delete(cloneDirectory, recursive: true); } } else { Console.WriteLine("To publish to NuGet, push a matching git tag for the release."); } }); string getPlatformArg() { string platformValue = platformOption.Value ?? settings?.SolutionPlatform; return(platformValue == null ? null : $"-p:Platform={platformValue}"); } string getMaxCpuCountArg() { if (settings.MaxCpuCount != null) { return($"-maxcpucount:{settings.MaxCpuCount}"); } else if (msbuildSettings != null) { return("-maxcpucount"); } else { return(null); } } IEnumerable <string> getExtraProperties(string target) { var pairs = settings.ExtraProperties?.Invoke(target); if (pairs != null) { foreach (var pair in pairs) { yield return($"-p:{pair.Key}={pair.Value}"); } } } void runMSBuild(IEnumerable <string> arguments) => RunMSBuild(msbuildSettings, arguments); }
public void CheckingOutCallsCheckoutNotify(CheckoutNotifyFlags notifyFlags, string expectedNotificationPath, bool isDirectory) { if (isDirectory) { expectedNotificationPath = expectedNotificationPath + Path.DirectorySeparatorChar; } string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { PopulateBasicRepository(repo); const string relativePathUpdated = "updated.txt"; Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text A"); repo.Stage(relativePathUpdated); repo.Commit("Commit initial update file", Constants.Signature, Constants.Signature); // Create conflicting change const string relativePathConflict = "conflict.txt"; Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text A"); repo.Stage(relativePathConflict); repo.Commit("Initial commit of conflict.txt and update.txt", Constants.Signature, Constants.Signature); // Create another branch repo.CreateBranch("newbranch"); // Make an edit to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text BB"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text BB"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on master branch", Constants.Signature, Constants.Signature); // Checkout other branch repo.Checkout("newbranch"); // Make alternate edits to conflict.txt and update.txt Touch(repo.Info.WorkingDirectory, relativePathUpdated, "updated file text CCC"); repo.Stage(relativePathUpdated); Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text CCC"); repo.Stage(relativePathConflict); repo.Commit("2nd commit of conflict.txt and update.txt on newbranch", Constants.Signature, Constants.Signature); // make conflicting change to conflict.txt Touch(repo.Info.WorkingDirectory, relativePathConflict, "conflict file text DDDD"); repo.Stage(relativePathConflict); // Create ignored change string relativePathIgnore = Path.Combine("bin", "ignored.txt"); Touch(repo.Info.WorkingDirectory, relativePathIgnore, "ignored file"); // Create untracked change const string relativePathUntracked = "untracked.txt"; Touch(repo.Info.WorkingDirectory, relativePathUntracked, "untracked file"); bool wasCalled = false; string actualNotificationPath = string.Empty; CheckoutNotifyFlags actualNotifyFlags = CheckoutNotifyFlags.None; CheckoutOptions options = new CheckoutOptions() { OnCheckoutNotify = (path, notificationType) => { wasCalled = true; actualNotificationPath = path; actualNotifyFlags = notificationType; return(true); }, CheckoutNotifyFlags = notifyFlags, }; Assert.Throws <CheckoutConflictException>(() => repo.Checkout("master", options)); Assert.True(wasCalled); Assert.Equal(expectedNotificationPath, actualNotificationPath); Assert.Equal(notifyFlags, actualNotifyFlags); } }
public void CreatingABranchFromANonCommitObjectThrows() { using (var repo = new Repository(BareTestRepoPath)) { const string name = "sorry-dude-i-do-not-do-blobs-nor-trees"; Assert.Throws<LibGit2Exception>(() => repo.CreateBranch(name, "refs/tags/point_to_blob")); Assert.Throws<LibGit2Exception>(() => repo.CreateBranch(name, "53fc32d")); Assert.Throws<LibGit2Exception>(() => repo.CreateBranch(name, "0266163")); } }
/// <summary> /// Don't rename to OnSelectedFileChanged as that messes things up with NotifyPropertyChanged.Fody /// </summary> /* * private void WhenSelectedFileChanged() * { * var selectedFile = SelectedFile; * * if (selectedFile == null) * { * return; * } * * string oldContentText; * string newContentText; * if (SelectedItemViewModel.Commit != null) * { * var commit = SelectedItemViewModel.Commit; * * var oldContent = (Blob)commit?.Parents.FirstOrDefault()?[selectedFile]?.Target; * var newContent = (Blob)commit?[selectedFile]?.Target; * * oldContentText = oldContent?.GetContentText(); * newContentText = newContent?.GetContentText(); * } * else * { * var oldContent = Repository.Lookup<Blob>(Repository.Index[selectedFile].Id); * // var oldContent = (Blob)Branch.Tip[selectedFile]?.Target; * oldContentText = oldContent?.GetContentText(); * * newContentText = File.ReadAllText(Path.Combine(Repository.Info.WorkingDirectory, selectedFile)).Replace("\r\n", "\n"); * } * * SelectedFileContent = DiffLineGenerator.GenerateLineDiffs(oldContentText, newContentText); * } * */ public void CreateBranch(string branchName) { Repository.CreateBranch(branchName); }
public async Task Execute() { var directory = _options.Directory; if (string.IsNullOrWhiteSpace(directory)) { _logger.LogDebug("Setting directory to current"); directory = Directory.GetCurrentDirectory(); } _logger.LogDebug("Checking for git repo"); if (!Repository.IsValid(directory)) { _logger.LogInformation($"{directory} is not a valid git repository"); return; } if (_options.Interval < 10) { _logger.LogInformation("The defined interval can't be smaller than 10 seconds"); return; } using var cts = new CancellationTokenSource(); void cancelToken(object sender, ConsoleCancelEventArgs e) { if (cts.IsCancellationRequested) { return; } _logger.LogDebug("Cancelled directory watcher"); e.Cancel = true; Console.CancelKeyPress -= cancelToken; cts.Cancel(); } Console.CancelKeyPress += cancelToken; using var repo = new Repository(directory); CheckOut(repo); var startBranch = repo.Head; switch (startBranch.FriendlyName) { case nameof(GitAutocommit): { _logger.LogInformation($"You're still on a {nameof(GitAutocommit)} branch."); _logger.LogInformation("This is most likely because a previous crash or unusual program termination. Please fix your repository first."); return; } case "master": { _logger.LogInformation("Warning: You're currently working on master branch!"); break; } } var startCommit = startBranch.Tip; var branch = repo.Branches[nameof(GitAutocommit)]; if (branch != null) { CreateBranch(repo, branch); } _logger.LogDebug("Creating auto commit branch"); repo.CreateBranch(nameof(GitAutocommit)); branch = repo.Branches[nameof(GitAutocommit)]; _logger.LogDebug("Checking out auto commit branch"); Commands.Checkout(repo, branch); var interval = TimeSpan.FromSeconds(_options.Interval); var autoCommitAuthor = new Signature(nameof(GitAutocommit), "@" + nameof(GitAutocommit), DateTime.Now); _logger.LogDebug($"Checking repo changes with an interval of {_options.Interval} seconds"); _logger.LogInformation($"Monitoring {directory} for changes"); await CommitChanges(interval, repo, autoCommitAuthor, cts); var currentHead = repo.Head.Tip; var hasChanges = currentHead != startBranch.Tip; string msg = ResolveCommitMessage(hasChanges); _logger.LogInformation("Checking out " + startBranch.FriendlyName); Commands.Checkout(repo, startBranch); if (hasChanges) { Commit(repo, startCommit, currentHead, msg); } _logger.LogInformation("Removing auto commit branch"); repo.Branches.Remove(branch); if (_options.AutoPush != null) { AutoPush(repo, startBranch); } _logger.LogInformation("Finished auto committing"); }
private void ConstructRebaseTestRepository(Repository repo, string attributes = "* text=auto", string lineEnding = "\r\n") { // Constructs a graph that looks like: // * -- * -- * (modifications to c.txt) // / | // / T2 // / // * -- * -- * (modifications to b.txt) // / | // / T1 // / // *--*--*--*--*--*---- // | | \ // M1 M2 \ // ---* // | // C1 const string fileContentA1 = "A1"; const string fileContentB1 = "B1"; const string fileContentB2 = "B2"; const string fileContentB3 = "B3"; const string fileContentB4 = "B4"; const string fileContentC1 = "C1"; const string fileContentC2 = "C2"; const string fileContentC3 = "C3"; const string fileContentC4 = "C4"; const string fileContentD1 = "D1"; const string fileContentD2 = "D2"; const string fileContentD3 = "D3"; string workdir = repo.Info.WorkingDirectory; Commit commit = null; CreateAttributesFile(repo, attributes); Commands.Stage(repo, ".gitattributes"); commit = repo.Commit("setup", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathA, fileContentA1); Commands.Stage(repo, filePathA); commit = repo.Commit("commit 1", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathB, fileContentB1); Commands.Stage(repo, filePathB); commit = repo.Commit("commit 2", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathC, fileContentC1); Commands.Stage(repo, filePathC); commit = repo.Commit("commit 3", Constants.Signature, Constants.Signature, new CommitOptions()); Branch masterBranch1 = repo.CreateBranch(masterBranch1Name, commit); Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2)); Commands.Stage(repo, filePathB); commit = repo.Commit("commit 4", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2, fileContentB3)); Commands.Stage(repo, filePathB); commit = repo.Commit("commit 5", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2, fileContentB3, fileContentB4)); Commands.Stage(repo, filePathB); commit = repo.Commit("commit 6", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(topicBranch1Name, commit); Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2)); Commands.Stage(repo, filePathC); commit = repo.Commit("commit 7", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2, fileContentC3)); Commands.Stage(repo, filePathC); commit = repo.Commit("commit 8", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathC, string.Join(lineEnding, fileContentC1, fileContentC2, fileContentC3, fileContentC4)); Commands.Stage(repo, filePathC); commit = repo.Commit("commit 9", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(topicBranch2Name, commit); repo.Checkout(masterBranch1.Tip); Touch(workdir, filePathD, fileContentD1); Commands.Stage(repo, filePathD); commit = repo.Commit("commit 10", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathD, string.Join(lineEnding, fileContentD1, fileContentD2)); Commands.Stage(repo, filePathD); commit = repo.Commit("commit 11", Constants.Signature, Constants.Signature, new CommitOptions()); Touch(workdir, filePathD, string.Join(lineEnding, fileContentD1, fileContentD2, fileContentD3)); Commands.Stage(repo, filePathD); commit = repo.Commit("commit 12", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(masterBranch2Name, commit); // Create commit / branch that conflicts with T1 and T2 Touch(workdir, filePathB, string.Join(lineEnding, fileContentB1, fileContentB2 + fileContentB3 + fileContentB4)); Commands.Stage(repo, filePathB); commit = repo.Commit("commit 13", Constants.Signature, Constants.Signature, new CommitOptions()); repo.CreateBranch(conflictBranch1Name, commit); }
public void CreateBranch(string branchName) { LibGit2Sharp.Commands.Checkout(_repo, _repo.CreateBranch(branchName)); }
static void Main1(string[] args) { var server = @""; var dbName = ""; // "ZENITH_PRODUCTION"; var user = "******"; var password = ""; var workingDir = AppDomain.CurrentDomain.BaseDirectory; var outputDir = System.IO.Path.Combine(workingDir, directory); if (!System.IO.Directory.Exists(outputDir)) { System.IO.Directory.CreateDirectory(outputDir); } /// connection var conn = new ServerConnection(server, user, password); //conn.BeginTransaction(); //conn.CommitTransaction(); // server Server srv = new Server(conn); // database var db = srv.Databases[dbName]; db.CompatibilityLevel = CompatibilityLevel.Version100; // scripter engine Scripter scp = new Scripter(srv); #region Scripter Options scp.Options.NoCollation = true; scp.Options.NoCommandTerminator = true; // only schema scp.Options.ScriptSchema = true; scp.Options.ScriptData = false; // no GO's scp.Options.NoCommandTerminator = false; // without output stream (all objects at once) scp.Options.ToFileOnly = true; // objects defaults scp.Options.AllowSystemObjects = false; scp.Options.Permissions = true; scp.Options.SchemaQualify = true; scp.Options.AnsiFile = true; scp.Options.AnsiPadding = false; scp.Options.SchemaQualifyForeignKeysReferences = true; scp.Options.DriAllConstraints = true; scp.Options.DriIndexes = true; scp.Options.DriClustered = true; scp.Options.DriNonClustered = true; scp.Options.Indexes = true; scp.Options.NonClusteredIndexes = true; scp.Options.ClusteredIndexes = true; scp.Options.FullTextIndexes = true; scp.Options.EnforceScriptingOptions = true; /// case of our tests scp.Options.WithDependencies = false; #endregion var values = db.Tables["SAVGLOBALIZATION_VALUES"]; var globalization = db.Tables["SAVGLOBALIZATION_VALUES"]; using (var repo = new Repository(outputDir)) { var branchName = GetCurrentBranchName(); var branch = repo.CreateBranch(branchName); var master = repo.Branches["master"]; Commands.Checkout(repo, branch); // remove all .sql files before start foreach (var file in System.IO.Directory.GetFiles(outputDir, "*.SQL")) { System.IO.File.Delete(file); } scp.Options.ScriptSchema = false; scp.Options.ScriptData = true; scp.ExportFilesToScriptAndManifest(new[] { values.Urn, globalization.Urn }, "DataManifest.txt", null, outputDir: outputDir); scp.Options.ScriptSchema = true; scp.Options.ScriptData = false; // prepare tables to export var tables = db.Tables.Cast <Table>() .Where(tbl => !tbl.IsSystemObject) .Select(n => n.Urn).ToArray(); // Export it as manifest HashSet <Urn> hash = new HashSet <Urn>(); scp.FilterCallbackFunction = FilterTablesOnly; scp.ExportFilesToScriptAndManifest(tables, "TableManifest.txt", hash, outputDir: outputDir); // Export tables to script and manifest var views = db.Views.Cast <View>() .Where(vw => !vw.IsSystemObject) .Select(n => n.Urn).ToArray(); // Export views to script and manifest scp.FilterCallbackFunction = FilterViewsOnly; scp.ExportFilesToScriptAndManifest(views, "ViewManifest.txt", hash, outputDir: outputDir); Commands.Stage(repo, "*"); Signature author = new Signature("Felipe Correa", "*****@*****.**", DateTime.Now); Signature committer = author; var committed = repo.Commit(string.Format("Adds {0} ", branchName), author, committer); Commands.Checkout(repo, master); var result = repo.Merge(branch, author); repo.Branches.Remove(branch); } }
public void CheckStatus(bool forceUpdate = false) { var mustClone = false; Log.KeyValuePair(GetType().Name, $"Repository: {Configuration.Url}", Message.EContentType.MoreInfo); Log.Info(LocalStoragePath); try { // Try to create the local git clone storage, if not present; Directory.CreateDirectory(LocalStoragePath); Credentials GitHubCredentialsProvider(string url, string usernameFromUrl, SupportedCredentialTypes types) { return(new UsernamePasswordCredentials { Username = Configuration.Token, Password = "" }); } var pullOptions = new PullOptions { MergeOptions = new MergeOptions { FastForwardStrategy = FastForwardStrategy.Default }, FetchOptions = new FetchOptions { CredentialsProvider = GitHubCredentialsProvider } }; var cloneOptions = new CloneOptions { CredentialsProvider = GitHubCredentialsProvider }; var signature = new Signature(Host.ApplicationAssemblyName, "*****@*****.**", DateTimeOffset.Now); try { // Is it initialized? using var localRepo = new Repository(LocalStoragePath); if (Configuration.Branch != null) { var currentBranch = localRepo.Branches[Configuration.Branch]; if (currentBranch == null) { localRepo.CreateBranch(Configuration.Branch); currentBranch = localRepo.Branches[Configuration.Branch]; } if (currentBranch.FriendlyName != Configuration.Branch) { currentBranch = Commands.Checkout(localRepo, currentBranch); } } Log.Add(LocalStoragePath); var status = localRepo.RetrieveStatus(); // Always try to Fetch changes. var remote = localRepo.Network.Remotes.FirstOrDefault(); var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification).ToList(); Commands.Fetch(localRepo, remote.Name, refSpecs, pullOptions.FetchOptions, null); try { var mergeResult = Commands.Pull(localRepo, signature, pullOptions); if (mergeResult.Status == MergeStatus.UpToDate) { Log.KeyValuePair(GetType().Name, "Repository is up-to-date", Message.EContentType.MoreInfo); } else { Log.KeyValuePair(GetType().Name, mergeResult?.Commit?.Message.Replace("\n", " | ") ?? "Fetch/Pull finished.", Message.EContentType.MoreInfo); } } catch (Exception e) { Log.Add(e); } // Commit/push stragglers. if (status.IsDirty) { Log.KeyValuePair(GetType().Name, $"{status.Count()} uncommitted change(s)", Message.EContentType.MoreInfo); //try //{ // var commitOptions = new CommitOptions(); // localRepo.Commit(Host.ApplicationAssemblyName + " automatic sync", signature, signature, commitOptions); //} //catch (Exception) { } //var targetSpec = @"refs/heads/" + Configuration.Branch.Split('/')[1]; //localRepo.Network.Push(remote, targetSpec, new PushOptions {CredentialsProvider = GitHubCredentialsProvider}); } } catch (RepositoryNotFoundException e) { Log.KeyValuePair(GetType().Name, "Local repo not found. Attempting to create.", Message.EContentType.Maintenance); mustClone = true; } catch (Exception e) { Console.WriteLine(e); throw; } if (!mustClone) { return; } try { Log.KeyValuePair("Cloning", Configuration.Url, Message.EContentType.MoreInfo); Log.KeyValuePair("To", LocalStoragePath, Message.EContentType.MoreInfo); // Easy. Let's try to clone from source. Repository.Clone(Configuration.Url, LocalStoragePath, cloneOptions); Log.KeyValuePair("Status", "Success", Message.EContentType.MoreInfo); } catch (Exception e) { Console.WriteLine(e); } } catch (Exception e) { Console.WriteLine(e); } }
public void ConflictingMergeReposBinary() { const string firstBranchFileName = "first branch file.bin"; const string secondBranchFileName = "second branch file.bin"; const string sharedBranchFileName = "first+second branch file.bin"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); AddFileCommitToRepo(repo, sharedBranchFileName, "\0The first branches comment\0"); // Change file in first branch secondBranch.Checkout(); // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit). AddFileCommitToRepo(repo, secondBranchFileName); AddFileCommitToRepo(repo, sharedBranchFileName, "\0The second branches comment\0"); // Change file in second branch MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.Conflicts, mergeResult.Status); Assert.Equal(1, repo.Index.Conflicts.Count()); Conflict conflict = repo.Index.Conflicts.First(); var changes = repo.Diff.Compare(repo.Lookup<Blob>(conflict.Theirs.Id), repo.Lookup<Blob>(conflict.Ours.Id)); Assert.True(changes.IsBinaryComparison); } }
public static bool Run(CompressimagesParameters parameters, ICollector <CompressImagesMessage> compressImagesMessages, ILogger logger) { var storageAccount = CloudStorageAccount.Parse(Common.KnownEnvironmentVariables.AzureWebJobsStorage); var paidPlan = PaidPlan(storageAccount, parameters.RepoOwner); CredentialsHandler credentialsProvider = (url, user, cred) => new UsernamePasswordCredentials { Username = KnownGitHubs.Username, Password = parameters.Password }; // clone var cloneOptions = new CloneOptions { CredentialsProvider = credentialsProvider, }; Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions); var repo = new Repository(parameters.LocalPath); var remote = repo.Network.Remotes["origin"]; var isWikiCompress = parameters.CloneUrl.EndsWith(".wiki.git"); // check if we have the branch already or this is empty repo try { if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false) { logger.LogInformation("CompressImagesFunction: no references found for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } } catch (Exception e) { // log + ignore logger.LogWarning(e, "CompressImagesFunction: issue checking for existing branch or empty repo for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); } // check if the branch exists and has been modified by the user if (parameters.IsRebase && repo.Branches[$"refs/remotes/origin/{KnownGitHubs.BranchName}"].Tip.Author.Name != KnownGitHubs.ImgBotLogin) { logger.LogInformation("CompressImagesFunction: imgbot branch has been modified by the user."); return(false); } // check if we should switch away from the default branch if (!isWikiCompress && parameters.Settings != null && !string.IsNullOrEmpty(parameters.Settings.DefaultBranchOverride)) { logger.LogInformation( "CompressImagesFunction: default branch override for {Owner}/{RepoName} is {DefaultBranchOverride}", parameters.RepoOwner, parameters.RepoName, parameters.Settings.DefaultBranchOverride); var baseBranch = repo.Branches[$"refs/remotes/origin/{parameters.Settings.DefaultBranchOverride}"]; if (baseBranch == null) { logger.LogWarning( "CompressImagesFunction: default branch ({DefaultBranchOverride}) not found for {Owner}/{RepoName}", parameters.Settings.DefaultBranchOverride, parameters.RepoOwner, parameters.RepoName); return(false); } Commands.Checkout(repo, baseBranch); } var repoConfiguration = new RepoConfiguration(); try { // see if .imgbotconfig exists in repo root var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig"); if (!string.IsNullOrEmpty(repoConfigJson)) { repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson); // for now we are not adding the labels functionality || repoConfiguration.Labels.Any() TODO: add it when adding the labels feature if (paidPlan && (repoConfiguration.PrBody != null || repoConfiguration.PrTitle != null)) { var settingsTable = storageAccount.CreateCloudTableClient().GetTableReference("settings"); // Labels = repoConfiguration.Labels TODO: add it when adding the labels feature var settings = new Common.TableModels.Settings( parameters.CompressImagesMessage.InstallationId.ToString(), parameters.CompressImagesMessage.RepoName) { PrBody = repoConfiguration.PrBody, PrTitle = repoConfiguration.PrTitle, }; settingsTable.ExecuteAsync(TableOperation.InsertOrReplace(settings)).Wait(); } } } catch { // ignore } // Add new compressMessage if we should compress Wiki if (repoConfiguration.CompressWiki && isWikiCompress == false) { logger.LogInformation("CompressImagesFunction: Adding Wiki image compression to queue for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); compressImagesMessages.Add(new CompressImagesMessage() { InstallationId = parameters.CompressImagesMessage.InstallationId, RepoName = parameters.CompressImagesMessage.RepoName, Owner = parameters.RepoOwner, CloneUrl = $"https://github.com/{parameters.RepoOwner}/{parameters.RepoName}.wiki.git" }); } if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false) { logger.LogInformation("CompressImagesFunction: skipping optimization due to schedule for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } // Should not create branch if we are compressing Wiki or performing rebase if (isWikiCompress == false && !parameters.IsRebase) { // check out the branch repo.CreateBranch(KnownGitHubs.BranchName); var branch = Commands.Checkout(repo, KnownGitHubs.BranchName); } else if (parameters.IsRebase) { // if rebasing, fetch the branch var refspec = string.Format("{0}:{0}", KnownGitHubs.BranchName); Commands.Fetch(repo, "origin", new List <string> { refspec }, null, "fetch"); } // reset any mean files repo.Reset(ResetMode.Mixed, repo.Head.Tip); // optimize images var imagePaths = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration); var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths, logger, repoConfiguration.AggressiveCompression); if (optimizedImages.Length == 0) { return(false); } if (!Threshold.MeetsThreshold(repoConfiguration, optimizedImages)) { logger.LogInformation($"Did not meet threshold. {parameters.RepoOwner}/{parameters.RepoName}"); return(false); } // create commit message based on optimizations foreach (var image in optimizedImages) { Commands.Stage(repo, image.OriginalPath); } var commitMessage = CommitMessage.Create(optimizedImages); var signature = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now); repo.Commit(commitMessage, signature, signature); if (parameters.IsRebase) { var baseBranch = repo.Head; var newCommit = baseBranch.Tip; // we need to reset the default branch so that we can // rebase to it later. repo.Reset(ResetMode.Hard, repo.Head.Commits.ElementAt(1)); Commands.Checkout(repo, KnownGitHubs.BranchName); // reset imgbot branch removing old commit repo.Reset(ResetMode.Hard, repo.Head.Commits.ElementAt(1)); // cherry-pick var cherryPickOptions = new CherryPickOptions() { MergeFileFavor = MergeFileFavor.Theirs, }; var cherryPickResult = repo.CherryPick(newCommit, signature, cherryPickOptions); if (cherryPickResult.Status == CherryPickStatus.Conflicts) { var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions() { }); foreach (var item in status) { if (item.State == FileStatus.Conflicted) { Commands.Stage(repo, item.FilePath); } } repo.Commit(commitMessage, signature, signature); } // rebase var rebaseOptions = new RebaseOptions() { FileConflictStrategy = CheckoutFileConflictStrategy.Theirs, }; var rebaseResult = repo.Rebase.Start(repo.Head, baseBranch, null, new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions); while (rebaseResult.Status == RebaseStatus.Conflicts) { var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions() { }); foreach (var item in status) { if (item.State == FileStatus.Conflicted) { if (imagePaths.Contains(Path.Combine(parameters.LocalPath, item.FilePath))) { Commands.Stage(repo, item.FilePath); } else { Commands.Remove(repo, item.FilePath); } } } rebaseResult = repo.Rebase.Continue(new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions); } } // We just made a normal commit, now we are going to capture all the values generated from that commit // then rewind and make a signed commit var commitBuffer = Commit.CreateBuffer( repo.Head.Tip.Author, repo.Head.Tip.Committer, repo.Head.Tip.Message, repo.Head.Tip.Tree, repo.Head.Tip.Parents, true, null); var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKey, parameters.PgPPassword); repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha); var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData); repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep); // Should use "master" if we are compressing Wiki if (isWikiCompress) { var branchAgain = Commands.Checkout(repo, "master"); } else { var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName); } repo.Reset(ResetMode.Hard, commitToKeep.Sha); // verify images are not corrupted by reading from git // see https://github.com/dabutvin/ImgBot/issues/273 try { foreach (var image in optimizedImages) { if (image.OriginalPath.EndsWith(".svg")) { // do not use ImageMagick to verify SVGs continue; } new MagickImage(image.OriginalPath).Dispose(); } } catch (MagickErrorException) { logger.LogError("Corrupt images after reset!"); return(false); } // push to GitHub if (isWikiCompress) { repo.Network.Push(remote, "refs/heads/master", new PushOptions { CredentialsProvider = credentialsProvider, }); } else { var refs = $"refs/heads/{KnownGitHubs.BranchName}"; if (parameters.IsRebase) { refs = refs.Insert(0, "+"); } logger.LogInformation("refs: {refs}", refs); repo.Network.Push(remote, refs, new PushOptions { CredentialsProvider = credentialsProvider, }); } try { Directory.Delete(parameters.LocalPath, true); } catch (Exception e) { logger.LogError(e, $"Delete issue with repository {parameters.LocalPath}"); } return(true); }
public SourceControlResult SyncLocalRepository(string repoDir, string[] branchMatchers) { branchMatchers = branchMatchers ?? new string[0]; using (var repo = new Repository(repoDir)) { FetchFromAllRemotes(repo); var branchesToProcess = FilterBranchesByMatchers(repo.Branches.ToList(), branchMatchers); var branchesToProcessInitialCount = branchesToProcess.Count; var branchesToProcessCurrentCount = 0; _logger.Information( "Found {Count} branch(es) starting with at least of the following matchers {BranchMatchers}...", branchesToProcess.Count, branchMatchers); // Prepare for pull var signature = new Signature(_userInfo.Username, _userInfo.Email, DateTimeOffset.Now); var pullOptions = new PullOptions { FetchOptions = new FetchOptions { CredentialsProvider = (url, usernameFromUrl, types) => _credentials }, MergeOptions = new MergeOptions { FastForwardStrategy = FastForwardStrategy.Default } }; var localTrackingBranches = branchesToProcess .Where(branch => !branch.IsRemote) .Where(branch => !branch.FriendlyName.EndsWith("/HEAD")) .Where(branch => branch.IsTracking) .ToList(); var remoteBranches = branchesToProcess .Where(branch => branch.IsRemote) .Where(branch => !branch.FriendlyName.EndsWith("/HEAD")) // Where local branch tracking this remote does not exist .Where(branch => !localTrackingBranches.Any(x => x.TrackedBranch.FriendlyName.Equals(branch.FriendlyName))) .ToList(); // Checkout branches that do not have local branches that track remotes branchesToProcess = branchesToProcess.Except(remoteBranches).ToList(); foreach (var branch in remoteBranches) { branchesToProcessCurrentCount++; var localBranchName = branch.UpstreamBranchCanonicalName.Substring("refs/heads/".Length, branch.UpstreamBranchCanonicalName.Length - "refs/heads/".Length); _logger.Information("Branch {BranchName} does not exist locally. Creating", localBranchName); var localBranch = repo.CreateBranch(localBranchName, branch.Tip); repo.Branches.Update(localBranch, b => b.TrackedBranch = branch.CanonicalName); _logger.Information("Checking out [{Index}/{Count}] {BranchName}...", branchesToProcessCurrentCount, branchesToProcessInitialCount, localBranch.FriendlyName); Commands.Checkout(repo, localBranch, new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force }); } // Checkout and pull local branches that track remotes branchesToProcess = branchesToProcess.Except(localTrackingBranches).ToList(); foreach (var branch in localTrackingBranches) { _logger.Information("Checking out [{Index}/{Count}] {BranchName}...", branchesToProcessCurrentCount, branchesToProcessInitialCount, branch.FriendlyName); var checkoutOptions = new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force }; Commands.Checkout(repo, branch, checkoutOptions); _logger.Information("Pulling {BranchName}...", branch.FriendlyName); Commands.Pull(repo, signature, pullOptions); } if (branchesToProcess.Any()) { _logger.Warning("Found {Count} branches that weren't processed. {Branches}", branchesToProcess.Count, string.Join(",", branchesToProcess.Select(x => x.FriendlyName))); } } return(SourceControlResultFactory.MakeSuccessful); }
private Branch CheckoutDeploymentManifest(Repository gitRepository, ApplicationSourceRepository repository, UsernamePasswordGitCredentials credentials) { _log.LogInformation("CheckoutDeploymentManifest ..."); var branchNames = gitRepository.Branches.Select(x => x.CanonicalName).ToList(); var branch = gitRepository.Branches.FirstOrDefault(b => b.FriendlyName == repository.Ref); var originBranch = gitRepository.Branches.FirstOrDefault(b => b.FriendlyName == $"origin/{repository.Ref}"); if (branch != null || originBranch != null) { if (branch == null) { // checkout branch from origin and make sure we are tracking the remote branchb branch = gitRepository.CreateBranch(repository.Ref, originBranch.Tip); branch = gitRepository.Branches.Update(branch, b => b.TrackedBranch = originBranch.CanonicalName ); } // we already have a local copy of the branch, make sure it's the current head (if not switch to it) if (branch.Tip != gitRepository.Head.Tip) { // switch to selected branch _log.LogInformation("Switching from branch {currentBranch} to {requestedBranch}", gitRepository.Head.CanonicalName, branch.CanonicalName); Commands.Checkout(gitRepository, branch); } var currentHash = gitRepository.Head.Tip.Sha; _log.LogInformation("Fetching latest sources for {branch} [{currentHash}] ...", branch.CanonicalName, currentHash); // TODO maybe this needs to be a fetch Commands.Pull(gitRepository, new Signature("rig-deploy-bot", "*****@*****.**", DateTimeOffset.Now), new PullOptions() { FetchOptions = new FetchOptions() { Prune = true, CredentialsProvider = (url, fromUrl, types) => new UsernamePasswordCredentials() { Username = credentials.Username, Password = credentials.Password } }, MergeOptions = new MergeOptions() { FastForwardStrategy = FastForwardStrategy.FastForwardOnly } }); if (gitRepository.Head.Tip.Sha != currentHash) { _log.LogInformation("Branch changed, triggered application refresh"); } } else { var tag = gitRepository.Tags[repository.Ref]; if (tag != null) { var currentHash = tag.Target.Sha; Commands.Fetch( gitRepository, "origin", Enumerable.Empty <string>(), new FetchOptions() { Prune = true, CredentialsProvider = (url, fromUrl, types) => new UsernamePasswordCredentials() { Username = credentials.Username, Password = credentials.Password } }, null); tag = gitRepository.Tags[repository.Ref]; if (currentHash != tag.Target.Sha) { _log.LogInformation("Tag hash changed, triggered application refresh."); } } else { // its a git commit hash var currentHash = gitRepository.Head.Tip.Sha; if (currentHash != repository.Ref) { _log.LogInformation( $"Current hash [{currentHash}] is not requested hash [{repository.Ref}], git checkout of commit will be triggered."); Commands.Checkout(gitRepository, repository.Ref); } } } return(branch); }
public static bool Run(CompressimagesParameters parameters, ILogger logger) { CredentialsHandler credentialsProvider = (url, user, cred) => new UsernamePasswordCredentials { Username = KnownGitHubs.Username, Password = parameters.Password }; // clone var cloneOptions = new CloneOptions { CredentialsProvider = credentialsProvider, }; Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions); var repo = new Repository(parameters.LocalPath); var remote = repo.Network.Remotes["origin"]; // check if we have the branch already or this is empty repo try { if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false) { logger.LogInformation("CompressImagesFunction: no references found for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } if (repo.Network.ListReferences(remote, credentialsProvider).Any(x => x.CanonicalName == $"refs/heads/{KnownGitHubs.BranchName}")) { logger.LogInformation("CompressImagesFunction: branch already exists for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } } catch (Exception e) { // log + ignore logger.LogWarning(e, "CompressImagesFunction: issue checking for existing branch or empty repo for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); } var repoConfiguration = new RepoConfiguration(); try { // see if .imgbotconfig exists in repo root var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig"); if (!string.IsNullOrEmpty(repoConfigJson)) { repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson); } } catch { // ignore } if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false) { logger.LogInformation("CompressImagesFunction: skipping optimization due to schedule for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } // check out the branch repo.CreateBranch(KnownGitHubs.BranchName); var branch = Commands.Checkout(repo, KnownGitHubs.BranchName); // reset any mean files repo.Reset(ResetMode.Mixed, repo.Head.Tip); // optimize images var imagePaths = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration); var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths, logger, repoConfiguration.AggressiveCompression); if (optimizedImages.Length == 0) { return(false); } // create commit message based on optimizations foreach (var image in optimizedImages) { Commands.Stage(repo, image.OriginalPath); } var commitMessage = CommitMessage.Create(optimizedImages); var signature = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now); repo.Commit(commitMessage, signature, signature); // We just made a normal commit, now we are going to capture all the values generated from that commit // then rewind and make a signed commit var commitBuffer = Commit.CreateBuffer( repo.Head.Tip.Author, repo.Head.Tip.Committer, repo.Head.Tip.Message, repo.Head.Tip.Tree, repo.Head.Tip.Parents, true, null); var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKey, parameters.PgPPassword); repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha); var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData); repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep); var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName); repo.Reset(ResetMode.Hard, commitToKeep.Sha); // verify images are not corrupted by reading from git // see https://github.com/dabutvin/ImgBot/issues/273 try { foreach (var image in optimizedImages) { new MagickImage(image.OriginalPath).Dispose(); } } catch (MagickErrorException) { logger.LogError("Corrupt images after reset!"); return(false); } // push to GitHub repo.Network.Push(remote, $"refs/heads/{KnownGitHubs.BranchName}", new PushOptions { CredentialsProvider = credentialsProvider, }); return(true); }
private static void CloneAndPullRepo(int i, List <RepositoryModel> listRepositories, string userName, string password) { var stopWatch = Stopwatch.StartNew(); var repoModel = listRepositories[i]; var repoLink = repoModel.links.clone.FirstOrDefault()?.href; var repoFolder = Path.Combine(RepoBaseFolder, repoModel.full_name); var repoFolderInfo = new DirectoryInfo(repoFolder); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write($"{i + 1}."); Console.ResetColor(); Console.Write($" {repoLink} > {repoFolder}"); if (!repoFolderInfo.Exists) { Repository.Clone(repoLink, repoFolder, new CloneOptions { CredentialsProvider = (s, fromUrl, types) => new UsernamePasswordCredentials { Username = userName, Password = password } }); } var repo = new Repository(repoFolder); var branches = repo.Branches; if (repoFolderInfo.Exists) { stopWatch.Stop(); Console.Write($"[{branches.Count()} Branches]"); Console.ForegroundColor = ConsoleColor.Cyan; Console.Write($" [{stopWatch.Elapsed.TotalSeconds} s]"); Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine(" [Skipped]"); Console.ResetColor(); return; } foreach (var branch in branches) { if (!branch.IsRemote) { continue; } var pullBranch = repo.CreateBranch(branch.FriendlyName, branch.Tip); var pulledBranch = repo.Branches.Update(pullBranch, b => { b.TrackedBranch = branch.CanonicalName; }); } stopWatch.Stop(); stopWatch.Stop(); Console.Write($"[{branches.Count()} Branches]"); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($" [{stopWatch.Elapsed.TotalSeconds} s]"); Console.ResetColor(); }
public void CanCommitALittleBit() { string repoPath = InitNewRepository(); var identity = Constants.Identity; using (var repo = new Repository(repoPath, new RepositoryOptions { Identity = identity })) { string dir = repo.Info.Path; Assert.True(Path.IsPathRooted(dir)); Assert.True(Directory.Exists(dir)); const string relativeFilepath = "new.txt"; string filePath = Touch(repo.Info.WorkingDirectory, relativeFilepath, "null"); repo.Stage(relativeFilepath); File.AppendAllText(filePath, "token\n"); repo.Stage(relativeFilepath); Assert.Null(repo.Head[relativeFilepath]); var author = Constants.Signature; const string shortMessage = "Initial egotistic commit"; const string commitMessage = shortMessage + "\n\nOnly the coolest commits from us"; var before = DateTimeOffset.Now.TruncateMilliseconds(); Commit commit = repo.Commit(commitMessage, author, author); AssertBlobContent(repo.Head[relativeFilepath], "nulltoken\n"); AssertBlobContent(commit[relativeFilepath], "nulltoken\n"); Assert.Equal(0, commit.Parents.Count()); Assert.False(repo.Info.IsHeadUnborn); // Assert a reflog entry is created on HEAD Assert.Equal(1, repo.Refs.Log("HEAD").Count()); var reflogEntry = repo.Refs.Log("HEAD").First(); Assert.Equal(identity.Name, reflogEntry.Committer.Name); Assert.Equal(identity.Email, reflogEntry.Committer.Email); var now = DateTimeOffset.Now; Assert.InRange(reflogEntry.Committer.When, before, now); Assert.Equal(commit.Id, reflogEntry.To); Assert.Equal(ObjectId.Zero, reflogEntry.From); Assert.Equal(string.Format("commit (initial): {0}", shortMessage), reflogEntry.Message); // Assert a reflog entry is created on HEAD target var targetCanonicalName = repo.Refs.Head.TargetIdentifier; Assert.Equal(1, repo.Refs.Log(targetCanonicalName).Count()); Assert.Equal(commit.Id, repo.Refs.Log(targetCanonicalName).First().To); File.WriteAllText(filePath, "nulltoken commits!\n"); repo.Stage(relativeFilepath); var author2 = new Signature(author.Name, author.Email, author.When.AddSeconds(5)); Commit commit2 = repo.Commit("Are you trying to fork me?", author2, author2); AssertBlobContent(repo.Head[relativeFilepath], "nulltoken commits!\n"); AssertBlobContent(commit2[relativeFilepath], "nulltoken commits!\n"); Assert.Equal(1, commit2.Parents.Count()); Assert.Equal(commit.Id, commit2.Parents.First().Id); // Assert the reflog is shifted Assert.Equal(2, repo.Refs.Log("HEAD").Count()); Assert.Equal(reflogEntry.To, repo.Refs.Log("HEAD").First().From); Branch firstCommitBranch = repo.CreateBranch("davidfowl-rules", commit); repo.Checkout(firstCommitBranch); File.WriteAllText(filePath, "davidfowl commits!\n"); var author3 = new Signature("David Fowler", "*****@*****.**", author.When.AddSeconds(2)); repo.Stage(relativeFilepath); Commit commit3 = repo.Commit("I'm going to branch you backwards in time!", author3, author3); AssertBlobContent(repo.Head[relativeFilepath], "davidfowl commits!\n"); AssertBlobContent(commit3[relativeFilepath], "davidfowl commits!\n"); Assert.Equal(1, commit3.Parents.Count()); Assert.Equal(commit.Id, commit3.Parents.First().Id); AssertBlobContent(firstCommitBranch[relativeFilepath], "nulltoken\n"); } }
public static Branch GetOrCreateBranch(this Repository repo, string branchName) { return(repo.Branches[branchName] ?? repo.CreateBranch(branchName)); }
public void BranchTo(string branchName, string @as = null) { _sequenceDiagram.BranchTo(branchName, Repository.Head.FriendlyName, @as); Repository.Checkout(Repository.CreateBranch(branchName)); }
public Task <SourceRepository> FetchAllFiles(BuildConfig config) { var result = new SourceRepository(); string gitFolder = config.BuildFolder + "\\git"; //// temporary hack... //// git-pull does not work //if (Directory.Exists(gitFolder)) { // Directory.Delete(gitFolder, true); //} if (!Directory.Exists(gitFolder)) { Directory.CreateDirectory(gitFolder); Console.WriteLine("Cloning repository " + config.SourceUrl); CloneOptions clone = new CloneOptions(); clone.CredentialsProvider = CredentialsHandler; Repository.Clone(config.SourceUrl, gitFolder, clone); Console.WriteLine("Repository clone successful"); } Console.WriteLine("Fetching remote Repository"); using (var rep = new Repository(gitFolder)) { FetchOptions options = new FetchOptions(); options.CredentialsProvider = CredentialsHandler; Remote remote = rep.Network.Remotes["origin"]; //Commands.Fetch(rep,remote.Name,) //rep.Fetch(remote.Name, options); if (!string.IsNullOrWhiteSpace(config.SourceBranch) && config.SourceBranch != "master") { if (rep.Head.FriendlyName != config.SourceBranch) { Branch updatedBranch = rep.Branches[config.SourceBranch]; if (updatedBranch == null) { string remoteBranchName = "origin/" + config.SourceBranch; var remoteBranch = rep.Branches.FirstOrDefault(x => x.FriendlyName == remoteBranchName); if (remoteBranch == null) { throw new ArgumentException($"Branch {remoteBranch} not found in {string.Join(",", rep.Branches.Select(x => x.FriendlyName))}"); } var localBranch = rep.CreateBranch(config.SourceBranch, remoteBranch.Tip); updatedBranch = rep.Branches.Update(localBranch, x => x.TrackedBranch = remoteBranch.CanonicalName); } Commands.Checkout(rep, updatedBranch, new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force }); } } var merge = Commands.Pull(rep, new Signature("IISCI", "*****@*****.**", DateTime.Now), new PullOptions() { FetchOptions = options, MergeOptions = new MergeOptions() { MergeFileFavor = MergeFileFavor.Theirs, CommitOnSuccess = true } }); Console.WriteLine("Fetch successful"); result.LatestVersion = Convert.ToBase64String(rep.Head.Tip.Id.RawId); } List <ISourceItem> files = result.Files; EnumerateFiles(new DirectoryInfo(gitFolder), files, ""); //var md5 = System.Security.Cryptography.MD5.Create(); Parallel.ForEach(files, file => { ((GitSourceItem)file).Version = HashService.Instance.ComputeHash(file.Url); }); return(Task.FromResult(result)); }
public static bool Run(CompressimagesParameters parameters, ICollector <CompressImagesMessage> compressImagesMessages, ILogger logger) { CredentialsHandler credentialsProvider = (url, user, cred) => new UsernamePasswordCredentials { Username = KnownGitHubs.Username, Password = parameters.Password }; // clone var cloneOptions = new CloneOptions { CredentialsProvider = credentialsProvider, }; Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions); var repo = new Repository(parameters.LocalPath); var remote = repo.Network.Remotes["origin"]; var isWikiCompress = parameters.CloneUrl.EndsWith(".wiki.git"); // check if we have the branch already or this is empty repo try { if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false) { logger.LogInformation("CompressImagesFunction: no references found for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } if (!parameters.IsRebase && repo.Network.ListReferences(remote, credentialsProvider).Any(x => x.CanonicalName == $"refs/heads/{KnownGitHubs.BranchName}")) { logger.LogInformation("CompressImagesFunction: branch already exists for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } } catch (Exception e) { // log + ignore logger.LogWarning(e, "CompressImagesFunction: issue checking for existing branch or empty repo for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); } // check if we should switch away from the default branch if (!isWikiCompress && parameters.Settings != null && !string.IsNullOrEmpty(parameters.Settings.DefaultBranchOverride)) { logger.LogInformation( "CompressImagesFunction: default branch override for {Owner}/{RepoName} is {DefaultBranchOverride}", parameters.RepoOwner, parameters.RepoName, parameters.Settings.DefaultBranchOverride); var baseBranch = repo.Branches[$"refs/remotes/origin/{parameters.Settings.DefaultBranchOverride}"]; if (baseBranch == null) { logger.LogWarning( "CompressImagesFunction: default branch ({DefaultBranchOverride}) not found for {Owner}/{RepoName}", parameters.Settings.DefaultBranchOverride, parameters.RepoOwner, parameters.RepoName); return(false); } Commands.Checkout(repo, baseBranch); } var repoConfiguration = new RepoConfiguration(); try { // see if .imgbotconfig exists in repo root var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig"); if (!string.IsNullOrEmpty(repoConfigJson)) { repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson); } } catch { // ignore } // Add new compressMessage if we should compress Wiki if (repoConfiguration.CompressWiki && isWikiCompress == false) { logger.LogInformation("CompressImagesFunction: Adding Wiki image compression to queue for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); compressImagesMessages.Add(new CompressImagesMessage() { InstallationId = parameters.CompressImagesMessage.InstallationId, RepoName = parameters.CompressImagesMessage.RepoName, Owner = parameters.RepoOwner, CloneUrl = $"https://github.com/{parameters.RepoOwner}/{parameters.RepoName}.wiki.git" }); } if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false) { logger.LogInformation("CompressImagesFunction: skipping optimization due to schedule for {Owner}/{RepoName}", parameters.RepoOwner, parameters.RepoName); return(false); } // Should not create branch if we are compressing Wiki or performing rebase if (isWikiCompress == false && !parameters.IsRebase) { // check out the branch repo.CreateBranch(KnownGitHubs.BranchName); var branch = Commands.Checkout(repo, KnownGitHubs.BranchName); } // reset any mean files repo.Reset(ResetMode.Mixed, repo.Head.Tip); // optimize images string[] imagePaths; List <string> addedOrModifiedImagePaths = new List <string>(); List <string> deletedImagePaths = new List <string>(); if (parameters.IsRebase) { var refspec = string.Format("{0}:{0}", KnownGitHubs.BranchName); Commands.Fetch(repo, "origin", new List <string> { refspec }, null, "fetch"); var diff = repo.Diff.Compare <TreeChanges>(repo.Branches[KnownGitHubs.BranchName].Commits.ElementAt(1).Tree, repo.Head.Tip.Tree); if (diff == null) { logger.LogInformation("Something went wrong while doing rebase"); return(false); } foreach (TreeEntryChanges c in diff) { if (KnownImgPatterns.ImgExtensions.Contains(Path.GetExtension(c.Path))) { var path = parameters.LocalPath + "/" + c.Path; var oldpath = parameters.LocalPath + "/" + c.OldPath; switch (c.Status) { case ChangeKind.Added: case ChangeKind.Modified: addedOrModifiedImagePaths.Add(path.Replace("\\", "/")); break; case ChangeKind.Renamed: addedOrModifiedImagePaths.Add(path.Replace("\\", "/")); deletedImagePaths.Add(oldpath.Replace("\\", "/")); break; case ChangeKind.Deleted: deletedImagePaths.Add(path.Replace("\\", "/")); break; } } } imagePaths = ImageQuery.FilterOutIgnoredFiles(addedOrModifiedImagePaths, repoConfiguration); } else { imagePaths = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration); } var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths, logger, repoConfiguration.AggressiveCompression); if (optimizedImages.Length == 0) { return(false); } // create commit message based on optimizations foreach (var image in optimizedImages) { Commands.Stage(repo, image.OriginalPath); } var commitMessage = CommitMessage.Create(optimizedImages); var signature = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now); repo.Commit(commitMessage, signature, signature); if (parameters.IsRebase) { var baseBranch = repo.Head; var newCommit = baseBranch.Tip; var oldCommit = repo.Branches[KnownGitHubs.BranchName].Tip; // we need to reset the default branch so that we can // rebase to it later. repo.Reset(ResetMode.Hard, repo.Head.Commits.ElementAt(1)); // checkout to imgbot branch. TODO: remove because this is needed earlier on diff Commands.Checkout(repo, KnownGitHubs.BranchName); // cherry-pick var cherryPickOptions = new CherryPickOptions() { MergeFileFavor = MergeFileFavor.Theirs, }; var cherryPickResult = repo.CherryPick(newCommit, signature, cherryPickOptions); if (cherryPickResult.Status == CherryPickStatus.Conflicts) { var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions() { }); foreach (var item in status) { if (item.State == FileStatus.Conflicted) { Commands.Stage(repo, item.FilePath); } } repo.Commit(commitMessage, signature, signature); } // New commit message creation var previousCommitResults = CompressionResult.ParseCommitMessage(oldCommit.Message); var mergedResults = CompressionResult.Merge(optimizedImages, previousCommitResults); var filteredResults = CompressionResult.Filter(mergedResults, deletedImagePaths.ToArray()); var squashCommitMessage = CommitMessage.Create(filteredResults); // squash var baseCommit = repo.Head.Commits.ElementAt(2); repo.Reset(ResetMode.Soft, baseCommit); repo.Commit(squashCommitMessage, signature, signature); // rebase var rebaseOptions = new RebaseOptions() { FileConflictStrategy = CheckoutFileConflictStrategy.Theirs, }; var rebaseResult = repo.Rebase.Start(repo.Head, baseBranch, null, new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions); while (rebaseResult.Status == RebaseStatus.Conflicts) { var status = repo.RetrieveStatus(new LibGit2Sharp.StatusOptions() { }); foreach (var item in status) { if (item.State == FileStatus.Conflicted) { if (imagePaths.Contains(parameters.LocalPath + "/" + item.FilePath)) { Commands.Stage(repo, item.FilePath); } else { Commands.Remove(repo, item.FilePath); } } } rebaseResult = repo.Rebase.Continue(new Identity(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail), rebaseOptions); } } // We just made a normal commit, now we are going to capture all the values generated from that commit // then rewind and make a signed commit var commitBuffer = Commit.CreateBuffer( repo.Head.Tip.Author, repo.Head.Tip.Committer, repo.Head.Tip.Message, repo.Head.Tip.Tree, repo.Head.Tip.Parents, true, null); var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKey, parameters.PgPPassword); repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha); var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData); repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep); // Should use "master" if we are compressing Wiki if (isWikiCompress) { var branchAgain = Commands.Checkout(repo, "master"); } else { var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName); } repo.Reset(ResetMode.Hard, commitToKeep.Sha); // verify images are not corrupted by reading from git // see https://github.com/dabutvin/ImgBot/issues/273 try { foreach (var image in optimizedImages) { if (image.OriginalPath.EndsWith(".svg")) { // do not use ImageMagick to verify SVGs continue; } new MagickImage(image.OriginalPath).Dispose(); } } catch (MagickErrorException) { logger.LogError("Corrupt images after reset!"); return(false); } // push to GitHub if (isWikiCompress) { repo.Network.Push(remote, "refs/heads/master", new PushOptions { CredentialsProvider = credentialsProvider, }); } else { var refs = $"refs/heads/{KnownGitHubs.BranchName}"; if (parameters.IsRebase) { refs = refs.Insert(0, "+"); } logger.LogInformation("refs: {refs}", refs); repo.Network.Push(remote, refs, new PushOptions { CredentialsProvider = credentialsProvider, }); } return(true); }
private static void FeedTheRepository(Repository repo) { string fullPath = Path.Combine(repo.Info.WorkingDirectory, "a.txt"); File.WriteAllText(fullPath, "Hello\n"); repo.Index.Stage(fullPath); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); repo.ApplyTag("mytag"); File.AppendAllText(fullPath, "World\n"); repo.Index.Stage(fullPath); Signature shiftedSignature = Constants.Signature.TimeShift(TimeSpan.FromMinutes(1)); repo.Commit("Update file", shiftedSignature, shiftedSignature); repo.CreateBranch("mybranch"); repo.Checkout("mybranch"); Assert.False(repo.Index.RetrieveStatus().IsDirty); }
public void CanFollowBranches(string specificRepoPath) { var repoPath = specificRepoPath ?? CreateEmptyRepository(); var path = "Test.txt"; var dummy = new string('a', 1024); using (var repo = new Repository(repoPath)) { var master0 = AddCommitToOdb(repo, "0. Initial commit for this test", path, "Before merge", dummy); var fix1 = AddCommitToOdb(repo, "1. Changed on fix", path, "Change on fix branch", dummy, master0); var master2 = AddCommitToOdb(repo, "2. Changed on master", path, "Independent change on master branch", dummy, master0); path = "New" + path; var fix3 = AddCommitToOdb(repo, "3. Changed and renamed on fix", path, "Another change on fix branch", dummy, fix1); var master4 = AddCommitToOdb(repo, "4. Changed and renamed on master", path, "Another independent change on master branch", dummy, master2); var master5 = AddCommitToOdb(repo, "5. Merged fix into master", path, "Manual resolution of merge conflict", dummy, master4, fix3); var master6 = AddCommitToOdb(repo, "6. Changed on master", path, "Change after merge", dummy, master5); var nextfix7 = AddCommitToOdb(repo, "7. Changed on next-fix", path, "Change on next-fix branch", dummy, master6); var master8 = AddCommitToOdb(repo, "8. Changed on master", path, "Some arbitrary change on master branch", dummy, master6); var master9 = AddCommitToOdb(repo, "9. Merged next-fix into master", path, "Another manual resolution of merge conflict", dummy, master8, nextfix7); var master10 = AddCommitToOdb(repo, "10. Changed on master", path, "A change on master after merging", dummy, master9); repo.CreateBranch("master", master10); Commands.Checkout(repo, "master", new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force }); // Test --date-order. var timeHistory = repo.Commits.QueryBy(path, new CommitFilter { SortBy = CommitSortStrategies.Time }); var timeCommits = new List <Commit> { master10, // master master8, // master nextfix7, // next-fix master6, // master master4, // master fix3, // fix master2, // master fix1, // fix master0 // master (initial commit) }; Assert.Equal(timeCommits, timeHistory.Select(e => e.Commit)); // Test --topo-order. var topoHistory = repo.Commits.QueryBy(path, new CommitFilter { SortBy = CommitSortStrategies.Topological }); var topoCommits = new List <Commit> { master10, // master nextfix7, // next-fix master8, // master master6, // master fix3, // fix fix1, // fix master4, // master master2, // master master0 // master (initial commit) }; Assert.Equal(topoCommits, topoHistory.Select(e => e.Commit)); } }
public void CheckingOutWithMergeConflictsThrows() { string repoPath = InitNewRepository(); using (var repo = new Repository(repoPath)) { Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello\n"); repo.Stage(originalFilePath); repo.Commit("Initial commit", Constants.Signature, Constants.Signature); // Create 2nd branch repo.CreateBranch("branch2"); // Update file in main Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello from master!\n"); repo.Stage(originalFilePath); repo.Commit("2nd commit", Constants.Signature, Constants.Signature); // Checkout branch2 repo.Checkout("branch2"); Touch(repo.Info.WorkingDirectory, originalFilePath, "Hello From branch2!\n"); // Assert that checking out master throws // when there are unstaged commits Assert.Throws<MergeConflictException>(() => repo.Checkout("master")); // And when there are staged commits repo.Stage(originalFilePath); Assert.Throws<MergeConflictException>(() => repo.Checkout("master")); } }
public static bool Run(CompressimagesParameters parameters) { CredentialsHandler credentialsProvider = (url, user, cred) => new UsernamePasswordCredentials { Username = KnownGitHubs.Username, Password = parameters.Password }; // clone var cloneOptions = new CloneOptions { CredentialsProvider = credentialsProvider, }; Repository.Clone(parameters.CloneUrl, parameters.LocalPath, cloneOptions); var repo = new Repository(parameters.LocalPath); var remote = repo.Network.Remotes["origin"]; // check if we have the branch already or this is empty repo try { if (repo.Network.ListReferences(remote, credentialsProvider).Any() == false) { return(false); } if (repo.Network.ListReferences(remote, credentialsProvider).Any(x => x.CanonicalName == $"refs/heads/{KnownGitHubs.BranchName}")) { return(false); } } catch { // ignore } var repoConfiguration = new RepoConfiguration(); try { // see if .imgbotconfig exists in repo root var repoConfigJson = File.ReadAllText(parameters.LocalPath + Path.DirectorySeparatorChar + ".imgbotconfig"); if (!string.IsNullOrEmpty(repoConfigJson)) { repoConfiguration = JsonConvert.DeserializeObject <RepoConfiguration>(repoConfigJson); } } catch { // ignore } if (Schedule.ShouldOptimizeImages(repoConfiguration, repo) == false) { return(false); } // check out the branch repo.CreateBranch(KnownGitHubs.BranchName); var branch = Commands.Checkout(repo, KnownGitHubs.BranchName); // reset any mean files repo.Reset(ResetMode.Mixed, repo.Head.Tip); // optimize images var imagePaths = ImageQuery.FindImages(parameters.LocalPath, repoConfiguration); var optimizedImages = OptimizeImages(repo, parameters.LocalPath, imagePaths); if (optimizedImages.Length == 0) { return(false); } // create commit message based on optimizations var commitMessage = CommitMessage.Create(optimizedImages); // commit var signature = new Signature(KnownGitHubs.ImgBotLogin, KnownGitHubs.ImgBotEmail, DateTimeOffset.Now); repo.Commit(commitMessage, signature, signature); // We just made a normal commit, now we are going to capture all the values generated from that commit // then rewind and make a signed commit var commitBuffer = Commit.CreateBuffer( repo.Head.Tip.Author, repo.Head.Tip.Committer, repo.Head.Tip.Message, repo.Head.Tip.Tree, repo.Head.Tip.Parents, true, null); var signedCommitData = CommitSignature.Sign(commitBuffer + "\n", parameters.PgpPrivateKeyStream, parameters.PgPPassword); repo.Reset(ResetMode.Soft, repo.Head.Commits.Skip(1).First().Sha); var commitToKeep = repo.ObjectDatabase.CreateCommitWithSignature(commitBuffer, signedCommitData); repo.Refs.UpdateTarget(repo.Refs.Head, commitToKeep); var branchAgain = Commands.Checkout(repo, KnownGitHubs.BranchName); repo.Reset(ResetMode.Hard, commitToKeep.Sha); // push to GitHub repo.Network.Push(remote, $"refs/heads/{KnownGitHubs.BranchName}", new PushOptions { CredentialsProvider = credentialsProvider, }); return(true); }
private IGitTfsRemote InitTfsBranch(RemoteOptions remoteOptions, string tfsRepositoryPath, int rootChangesetId = -1, bool fetchParentBranch = false, string gitBranchNameExpected = null, IRenameResult renameResult = null) { Trace.WriteLine("Begin process of creating branch for remote :" + tfsRepositoryPath); // TFS string representations of repository paths do not end in trailing slashes tfsRepositoryPath = (tfsRepositoryPath ?? string.Empty).TrimEnd('/'); string gitBranchName = ExtractGitBranchNameFromTfsRepositoryPath( string.IsNullOrWhiteSpace(gitBranchNameExpected) ? tfsRepositoryPath : gitBranchNameExpected); if (string.IsNullOrWhiteSpace(gitBranchName)) { throw new GitTfsException("error: The Git branch name '" + gitBranchName + "' is not valid...\n"); } Trace.WriteLine("Git local branch will be :" + gitBranchName); string sha1RootCommit = null; if (rootChangesetId != -1) { sha1RootCommit = Repository.FindCommitHashByChangesetId(rootChangesetId); if (fetchParentBranch && string.IsNullOrWhiteSpace(sha1RootCommit)) { sha1RootCommit = FindRootRemoteAndFetch(rootChangesetId, renameResult); } if (string.IsNullOrWhiteSpace(sha1RootCommit)) { return(null); } Trace.WriteLine("Found commit " + sha1RootCommit + " for changeset :" + rootChangesetId); } IGitTfsRemote tfsRemote; if (Repository.HasRemote(gitBranchName)) { Trace.WriteLine("Remote already exist"); tfsRemote = Repository.ReadTfsRemote(gitBranchName); if (tfsRemote.TfsUrl != TfsUrl) { Trace.WriteLine("warning: Url is different"); } if (tfsRemote.TfsRepositoryPath != tfsRepositoryPath) { Trace.WriteLine("warning: TFS repository path is different"); } } else { Trace.WriteLine("Try creating remote..."); tfsRemote = Repository.CreateTfsRemote(new RemoteInfo { Id = gitBranchName, Url = TfsUrl, Repository = tfsRepositoryPath, RemoteOptions = remoteOptions }, string.Empty); } if (sha1RootCommit != null && !Repository.HasRef(tfsRemote.RemoteRef)) { if (!Repository.CreateBranch(tfsRemote.RemoteRef, sha1RootCommit)) { throw new GitTfsException("error: Fail to create remote branch ref file!"); } } Trace.WriteLine("Remote created!"); return(tfsRemote); }
Branch CreateBranch(string name, CommitNodeModel n) { return(Repository.CreateBranch(name, n.Commit)); }
public void CanMergeRepoNonFastForward(bool shouldMergeOccurInDetachedHeadState) { const string firstBranchFileName = "first branch file.txt"; const string secondBranchFileName = "second branch file.txt"; const string sharedBranchFileName = "first+second branch file.txt"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); var originalTreeCount = firstBranch.Tip.Tree.Count; // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); // Commit with ONE new file to first branch (FirstBranch moves forward as it is checked out, SecondBranch stays back one). AddFileCommitToRepo(repo, firstBranchFileName); if (shouldMergeOccurInDetachedHeadState) { // Detaches HEAD repo.Checkout(secondBranch.Tip); } else { secondBranch.Checkout(); } // Commit with ONE new file to second branch (FirstBranch and SecondBranch now point to separate commits that both have the same parent commit). AddFileCommitToRepo(repo, secondBranchFileName); MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.NonFastForward, mergeResult.Status); Assert.Equal(repo.Head.Tip, mergeResult.Commit); Assert.Equal(originalTreeCount + 3, mergeResult.Commit.Tree.Count); // Expecting original tree count plussed by the 3 added files. Assert.Equal(2, mergeResult.Commit.Parents.Count()); // Merge commit should have 2 parents Assert.Equal(shouldMergeOccurInDetachedHeadState, repo.Info.IsHeadDetached); if (!shouldMergeOccurInDetachedHeadState) { // Ensure HEAD is still attached and points to SecondBranch Assert.Equal(repo.Refs.Head.TargetIdentifier, secondBranch.CanonicalName); } } }
public void Checkout(string refspec = "master", CancellationToken token = default(CancellationToken)) { var checkoutOptions = new CheckoutOptions { CheckoutModifiers = CheckoutModifiers.Force, }; // Clone repository if it does not exist if (!Repository.IsValid(Source.RepositoryPath)) { Output.WriteLine("Cloning Repository...", ConsoleColor.DarkCyan); var cloneOptions = new CloneOptions(); cloneOptions.CredentialsProvider += CredentialsProvider; Repository.Clone(Source.RepositoryUrl, Source.RepositoryPath, cloneOptions); } using (var repo = new Repository(Source.RepositoryPath)) { // Fetch all updated refspecs and tags Output.WriteLine("Fetching updated refs...", ConsoleColor.DarkCyan); var fetchSpec = new[] { "+refs/heads/*:refs/remotes/origin/*" }; var fetchOptions = new FetchOptions { TagFetchMode = TagFetchMode.All, }; fetchOptions.CredentialsProvider += CredentialsProvider; LibGit2Sharp.Commands.Fetch(repo, "origin", fetchSpec, fetchOptions, null); // Find local and remote branches var remoteBranchName = $"refs/remotes/origin/{refspec}"; var remoteBranch = repo.Branches[remoteBranchName]; var localBranchName = $"refs/heads/origin/{refspec}"; var localBranch = repo.Branches[localBranchName]; if (remoteBranch == null) { Output.Write("Git Refspec ", ConsoleColor.DarkYellow) .Write(refspec, ConsoleColor.Yellow) .WriteLine(" was not found!", ConsoleColor.DarkYellow); throw new ApplicationException($"Git Refspec '{refspec}' was not found!"); } if (localBranch != null) { Output.WriteLine($"Found local branch '{localBranch.FriendlyName}'...", ConsoleColor.DarkCyan); // Update tracking branch if not remote branch if (!localBranch.IsTracking || localBranch.TrackedBranch != remoteBranch) { Output.WriteLine("Updating local branch tracking reference...", ConsoleColor.DarkCyan); repo.Branches.Update(localBranch, b => b.TrackedBranch = remoteBranch.CanonicalName); } // Checkout local branch if not current if (!localBranch.IsCurrentRepositoryHead) { Output.WriteLine($"Checkout local branch '{localBranch.FriendlyName}'...", ConsoleColor.DarkCyan); LibGit2Sharp.Commands.Checkout(repo, localBranch, checkoutOptions); } // Revert to common ancestor commit if diverged var status = localBranch.TrackingDetails; var aheadCount = status.AheadBy ?? 0; if (aheadCount > 0) { Output.WriteLine($"Local branch '{localBranch.FriendlyName}' has diverged from the remote tracking branch!", ConsoleColor.DarkYellow); var common = status.CommonAncestor; if (common != null) { Output.WriteLine($"Reverting local branch to commit '{common.Sha}'!", ConsoleColor.DarkCyan); repo.Reset(ResetMode.Hard, common, checkoutOptions); } } // Pull latest changes from remote Output.WriteLine("Pull changes from remote...", ConsoleColor.DarkCyan); var sign = new Signature("photon", "*****@*****.**", DateTimeOffset.Now); var pullOptions = new PullOptions { FetchOptions = fetchOptions, }; LibGit2Sharp.Commands.Pull(repo, sign, pullOptions); } else { // Create local branch tracking remote Output.WriteLine($"No local branch found. Creating local tracking branch '{remoteBranch.FriendlyName}'...", ConsoleColor.DarkCyan); localBranch = repo.CreateBranch(remoteBranch.FriendlyName, remoteBranch.Tip); repo.Branches.Update(localBranch, b => b.TrackedBranch = remoteBranch.CanonicalName); Output.WriteLine($"Checkout local tracking branch '{localBranch.FriendlyName}'...", ConsoleColor.DarkCyan); LibGit2Sharp.Commands.Checkout(repo, localBranch, checkoutOptions); } var commit = repo.Head?.Tip; CommitHash = commit?.Sha; CommitAuthor = commit?.Author?.Name; CommitMessage = commit?.Message; Output.WriteLine("Current Commit:", ConsoleColor.DarkBlue) .WriteLine($" {CommitHash}", ConsoleColor.Blue) .WriteLine($" {CommitAuthor}", ConsoleColor.Blue) .WriteLine(CommitMessage, ConsoleColor.Cyan); } }
public void IsUpToDateMerge() { const string sharedBranchFileName = "first+second branch file.txt"; string path = CloneStandardTestRepo(); using (var repo = new Repository(path)) { var firstBranch = repo.CreateBranch("FirstBranch"); firstBranch.Checkout(); // Commit with ONE new file to both first & second branch (SecondBranch is created on this commit). AddFileCommitToRepo(repo, sharedBranchFileName); var secondBranch = repo.CreateBranch("SecondBranch"); secondBranch.Checkout(); MergeResult mergeResult = repo.Merge(repo.Branches["FirstBranch"].Tip, Constants.Signature); Assert.Equal(MergeStatus.UpToDate, mergeResult.Status); } }
public void CreatingABranchTriggersTheCreationOfADirectReference() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { Branch newBranch = repo.CreateBranch("clone-of-master"); Assert.False(newBranch.IsCurrentRepositoryHead); ObjectId commitId = repo.Head.Tip.Id; Assert.Equal(commitId, newBranch.Tip.Id); Reference reference = repo.Refs[newBranch.CanonicalName]; Assert.NotNull(reference); Assert.IsType(typeof(DirectReference), reference); } }
public void CanCreateBranch(string name) { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { Branch newBranch = repo.CreateBranch(name, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644"); Assert.NotNull(newBranch); Assert.Equal(name, newBranch.Name); Assert.Equal("refs/heads/" + name, newBranch.CanonicalName); Assert.NotNull(newBranch.Tip); Assert.Equal("be3563ae3f795b2b4353bcce3a527ad0a4f7f644", newBranch.Tip.Sha); Assert.NotNull(repo.Branches.SingleOrDefault(p => p.Name == name)); repo.Branches.Delete(newBranch.Name); } }
public void CanCreateBranchUsingAbbreviatedSha() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "unit_test"; Branch newBranch = repo.CreateBranch(name, "be3563a"); Assert.Equal("refs/heads/" + name, newBranch.CanonicalName); Assert.Equal("be3563ae3f795b2b4353bcce3a527ad0a4f7f644", newBranch.Tip.Sha); } }
Branch CreateBranch(string name, BranchLabelModel l) { return(Repository.CreateBranch(name, l.Branch.Tip)); }
public static async Task <ConfigurationState <RunnerRepoInfo> > CheckoutRunnerRepository( string proj, string localRepoDir, GitPatcherVersioning patcherVersioning, NugetVersioningTarget nugetVersioning, Action <string>?logger, CancellationToken cancel, bool compile = true) { try { cancel.ThrowIfCancellationRequested(); logger?.Invoke($"Targeting {patcherVersioning}"); using var repo = new Repository(localRepoDir); var runnerBranch = repo.Branches[RunnerBranch] ?? repo.CreateBranch(RunnerBranch); repo.Reset(ResetMode.Hard); Commands.Checkout(repo, runnerBranch); string?targetSha; string?target; bool fetchIfMissing = patcherVersioning.Versioning switch { PatcherVersioningEnum.Commit => true, _ => false }; switch (patcherVersioning.Versioning) { case PatcherVersioningEnum.Tag: if (string.IsNullOrWhiteSpace(patcherVersioning.Target)) { return(GetResponse <RunnerRepoInfo> .Fail("No tag selected")); } repo.Fetch(); targetSha = repo.Tags[patcherVersioning.Target]?.Target.Sha; if (string.IsNullOrWhiteSpace(targetSha)) { return(GetResponse <RunnerRepoInfo> .Fail("Could not locate tag")); } target = patcherVersioning.Target; break; case PatcherVersioningEnum.Commit: targetSha = patcherVersioning.Target; if (string.IsNullOrWhiteSpace(targetSha)) { return(GetResponse <RunnerRepoInfo> .Fail("Could not locate commit")); } target = patcherVersioning.Target; break; case PatcherVersioningEnum.Branch: if (string.IsNullOrWhiteSpace(patcherVersioning.Target)) { return(GetResponse <RunnerRepoInfo> .Fail($"Target branch had no name.")); } repo.Fetch(); var targetBranch = repo.Branches[$"origin/{patcherVersioning.Target}"]; if (targetBranch == null) { return(GetResponse <RunnerRepoInfo> .Fail($"Could not locate branch: {patcherVersioning.Target}")); } targetSha = targetBranch.Tip.Sha; target = patcherVersioning.Target; break; default: throw new NotImplementedException(); } if (!ObjectId.TryParse(targetSha, out var objId)) { return(GetResponse <RunnerRepoInfo> .Fail("Malformed sha string")); } cancel.ThrowIfCancellationRequested(); var commit = repo.Lookup(objId, ObjectType.Commit) as Commit; if (commit == null) { if (!fetchIfMissing) { return(GetResponse <RunnerRepoInfo> .Fail("Could not locate commit with given sha")); } repo.Fetch(); commit = repo.Lookup(objId, ObjectType.Commit) as Commit; if (commit == null) { return(GetResponse <RunnerRepoInfo> .Fail("Could not locate commit with given sha")); } } cancel.ThrowIfCancellationRequested(); var slnPath = GitPatcherRun.GetPathToSolution(localRepoDir); if (slnPath == null) { return(GetResponse <RunnerRepoInfo> .Fail("Could not locate solution to run.")); } var foundProjSubPath = SolutionPatcherRun.AvailableProject(slnPath, proj); if (foundProjSubPath == null) { return(GetResponse <RunnerRepoInfo> .Fail($"Could not locate target project file: {proj}.")); } cancel.ThrowIfCancellationRequested(); logger?.Invoke($"Checking out {targetSha}"); repo.Reset(ResetMode.Hard, commit, new CheckoutOptions()); var projPath = Path.Combine(localRepoDir, foundProjSubPath); cancel.ThrowIfCancellationRequested(); logger?.Invoke($"Mutagen Nuget: {nugetVersioning.MutagenVersioning} {nugetVersioning.MutagenVersion}"); logger?.Invoke($"Synthesis Nuget: {nugetVersioning.SynthesisVersioning} {nugetVersioning.SynthesisVersion}"); GitPatcherRun.SwapInDesiredVersionsForSolution( slnPath, drivingProjSubPath: foundProjSubPath, mutagenVersion: nugetVersioning.MutagenVersioning == NugetVersioningEnum.Match ? null : nugetVersioning.MutagenVersion, listedMutagenVersion: out var listedMutagenVersion, synthesisVersion: nugetVersioning.SynthesisVersioning == NugetVersioningEnum.Match ? null : nugetVersioning.SynthesisVersion, listedSynthesisVersion: out var listedSynthesisVersion); // Compile to help prep if (compile) { var compileResp = await SolutionPatcherRun.CompileWithDotnet(projPath, cancel); if (compileResp.Failed) { return(compileResp.BubbleFailure <RunnerRepoInfo>()); } } return(GetResponse <RunnerRepoInfo> .Succeed( new RunnerRepoInfo( slnPath : slnPath, projPath : projPath, target : target, commitMsg : commit.Message, commitDate : commit.Author.When.LocalDateTime, listedSynthesis : listedSynthesisVersion, listedMutagen : listedMutagenVersion))); } catch (OperationCanceledException) { throw; } catch (Exception ex) { return(GetResponse <RunnerRepoInfo> .Fail(ex)); } }
public void CanCreateBranchFromCommit() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "unit_test"; var commit = repo.Lookup<Commit>("HEAD"); Branch newBranch = repo.CreateBranch(name, commit); Assert.NotNull(newBranch); Assert.Equal("4c062a6361ae6959e06292c1fa5e2822d9c96345", newBranch.Tip.Sha); } }
public static async void createPR(String stack) { String _gitToken = File.ReadAllText("../../../gitToken.txt"); // clone master String timeStamp = DateTime.Now.ToString("yyyyMMddHHmmss"); String root = String.Format("D:\\local\\temp\\blimpPR{0}", timeStamp); String upstream = root + "\\" + stack; String upstreamURL = String.Format("https://github.com/Azure-App-Service/{0}.git", stack); String branch = String.Format("blimp{0}", timeStamp); Repository.Clone(upstreamURL, upstream, new CloneOptions { BranchName = "dev" }); // branch Repository repo = new Repository(upstream); repo.CreateBranch(branch); Commands.Checkout(repo, branch); // list temp repos HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("patricklee2"); HttpResponseMessage response = null; List <Repo> resultList = new List <Repo>(); List <Repo> stackRepos = null; int run = 0; while (true) { String generatedReposURL = String.Format("https://api.github.com/orgs/{0}/repos?page={1}&per_page=30&sort=full_name&direction=asc", "blessedimagepipeline", run); response = await httpClient.GetAsync(generatedReposURL); response.EnsureSuccessStatusCode(); string contentString = await response.Content.ReadAsStringAsync(); List <Repo> l = JsonConvert.DeserializeObject <List <Repo> >(contentString); resultList.AddRange(l); run++; if (l.Count < 30) { break; } } switch (stack) { case "dotnetcore": stackRepos = resultList.FindAll(isDotnetcoreRepo); break; case "node": stackRepos = resultList.FindAll(isNodeRepo); break; case "php": stackRepos = resultList.FindAll(isPhpRepo); break; case "python": stackRepos = resultList.FindAll(isPythonRepo); break; case "ruby": stackRepos = resultList.FindAll(isRubyRepo); rubyBase(resultList.FindAll(isRubyBaseRepo), root, upstream); break; } // List<Repo> stackRepos = resultList.FindAll(isStackRepo(stack)); foreach (Repo r in stackRepos) { try { Console.WriteLine("copying " + r.full_name); // pull temps String dest = root + "\\" + r.name; Repository.Clone(r.clone_url, dest, new CloneOptions { BranchName = "dev" }); // move String version = r.name.ToLower().Replace(stack + "-", ""); String suffix = ""; if (stack.Equals("php")) { suffix = "-apache"; } GitHubUtils githubUtils = new GitHubUtils("fake"); githubUtils.Delete(upstream + "\\" + version + suffix, skipGit: true); githubUtils.DeepCopy(dest, upstream + "\\" + version + suffix); // stage Commands.Stage(repo, upstream + "\\" + version + suffix); } catch (LibGit2Sharp.NameConflictException e) { } catch (Exception e) { Console.WriteLine(e.ToString()); } } // git commit // Create the committer's signature and commit //_log.Info("git commit"); Signature author = new Signature("blimp", "*****@*****.**", DateTime.Now); Signature committer = author; // Commit to the repository try { Commit commit = repo.Commit("blimp", author, committer); } catch (Exception e) { //_log.info("Empty commit"); } Remote remote = repo.Network.Remotes.Add("upstream", upstreamURL); repo.Branches.Update(repo.Head, b => b.Remote = remote.Name, b => b.UpstreamBranch = repo.Head.CanonicalName); // git push //_log.Info("git push"); LibGit2Sharp.PushOptions options = new LibGit2Sharp.PushOptions(); options.CredentialsProvider = new CredentialsHandler( (url, usernameFromUrl, types) => new UsernamePasswordCredentials() { Username = _gitToken.Trim(), Password = String.Empty }); repo.Network.Push(repo.Branches[branch], options); // fails if branch already exists //create PR String pullRequestURL = String.Format("https://api.github.com/repos/{0}/{1}/pulls?access_token={2}", "azure-app-service", stack, _gitToken); String body = "{ " + "\"title\": " + JsonConvert.SerializeObject("sync from templates") + ", " + "\"body\": " + JsonConvert.SerializeObject("sync from templates") + ", " + "\"head\": " + JsonConvert.SerializeObject("azure-app-service:" + branch) + ", " + "\"base\": " + JsonConvert.SerializeObject("dev") + "}"; response = await httpClient.PostAsync(pullRequestURL, new StringContent(body)); // fails on empty commits String result = await response.Content.ReadAsStringAsync(); System.Console.WriteLine(response.ToString()); System.Console.WriteLine(result); if (response.StatusCode == HttpStatusCode.UnprocessableEntity) { System.Console.WriteLine("Unable to make PR due to no differnce"); } //cleanup //new DirectoryInfo(root).Delete(true); }
public void CanLookupABranchWhichNameIsMadeOfNon7BitsAsciiCharacters() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "Ångström"; Branch newBranch = repo.CreateBranch(name, "be3563a"); Assert.NotNull(newBranch); Branch retrieved = repo.Branches["Ångström"]; Assert.NotNull(retrieved); Assert.Equal(newBranch.Tip, retrieved.Tip); } }
private static FileInfo CommitFileOnBranch(Repository repo, string branchName, String content) { var branch = repo.CreateBranch(branchName); Commands.Checkout(repo, branch.FriendlyName); FileInfo expectedPath = StageNewFile(repo, content); repo.Commit("Commit", Constants.Signature, Constants.Signature); return expectedPath; }
public void CreatingABranchFromATagPeelsToTheCommit() { TemporaryCloneOfTestRepo path = BuildTemporaryCloneOfTestRepo(); using (var repo = new Repository(path.RepositoryPath)) { const string name = "i-peel-tag"; Branch newBranch = repo.CreateBranch(name, "refs/tags/test"); Assert.NotNull(newBranch); Assert.Equal("e90810b8df3e80c413d903f631643c716887138d", newBranch.Tip.Sha); } }
public void BranchToFromTag(string branchName, string fromTag, string onBranch, string @as = null) { _sequenceDiagram.BranchToFromTag(branchName, fromTag, onBranch, @as); Repository.Checkout(Repository.CreateBranch(branchName)); }
public void CreatingBranchWithBadParamsThrows() { using (var repo = new Repository(BareTestRepoPath)) { Assert.Throws<ArgumentNullException>(() => repo.Branches.Create(null, repo.Head.CanonicalName)); Assert.Throws<ArgumentException>(() => repo.Branches.Create(string.Empty, repo.Head.CanonicalName)); Assert.Throws<ArgumentNullException>(() => repo.Branches.Create("bad_branch", default(string))); Assert.Throws<ArgumentException>(() => repo.Branches.Create("bad_branch", string.Empty)); Assert.Throws<ArgumentNullException>(() => repo.CreateBranch("bad_branch", default(Commit))); } }
static int Main(string[] args) { // Get configration settings from the appsettings.json file. ConfigureApplication(); // Validate and cache arguments. if (!CheckArguments(args)) { Console.WriteLine(Usage); return(ErrorCode); } // Create a Repository instance on the local path to the git repo. using (var repo = new Repository(RepoLocalPath)) { // Fetch the state of the remote repo, which is typically named "upstream". PrintMessage($"Fetching state of {RemoteRepoName}"); var remote = repo.Network.Remotes[RemoteRepoName]; var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification); string logMessage = ""; Commands.Fetch(repo, remote.Name, refSpecs, null, logMessage); // Get the branch to cherry-pick from. var sourceBranch = repo.Branches[SourceBranchName]; if (sourceBranch == null) { // Repository returns a null object when the requested branch doesn't exist. PrintMessage($"Source branch {SourceBranchName} not found in {RemoteRepoName}, exiting."); return(ErrorCode); } else { PrintMessage($"Found branch {sourceBranch.FriendlyName} in {RemoteRepoName}"); } // Find the commit in the git log of the source branch. var sourceCommit = sourceBranch.Commits.FirstOrDefault(c => c.Sha == CommitSha); if (sourceCommit == null) { PrintMessage($"Commit {CommitSha} not found in {sourceBranch.FriendlyName}, no action taken, exiting."); return(ErrorCode); } // Get the branches to merge to, which is a list of the available // branches minus the source branch for the commit. var branchesToMerge = AvailableBranches.Where(b => b != SourceBranchName); // Assign cherry-pick options. CherryPickOptions options = CreateCherryPickOptions(); // Set up the signature for the cherry-pick message. Signature sig = new Signature(SigName, SigEmail, DateTime.Now); // Create local branches that track the available remote branches. // In each local branch, do the cherry-pick and push to the remote repo. PrintMessage($"Cherry-picking from {sourceBranch.FriendlyName} to available branches."); foreach (var trackedBranchName in branchesToMerge) { // Create and check out the local branch, which is equivalent to the command: // // git checkout -b <local-branch-name> -t <remote-repo-name>/<tracked-branch-name> // // For example, the following command creates a local branch // named "docs-2358" which tracks the remote branch named "0.8.1-ksqldb" // in the remote repo named "upstream": // // git checkout -b docs-2358 -t upstream/0.8.1-ksqldb // Name the local branch by appending the remote branch name to the provided base name. // For example, if the base name is "docs-2358" and the tracked branch is named // "0.8.1-ksqldb", the local branch name is "docs-2358-0.8.1-ksqldb". string localBranchName = $"{LocalBranchBaseName}-{trackedBranchName}"; // For future reference, this is the "objectish" representation: // string objectish = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", localBranch.CanonicalName, localBranch.UpstreamBranchCanonicalName); // Get a reference on the remote tracking branch. Branch trackedBranch = repo.Branches[$"{RemoteRepoName}/{trackedBranchName}"]; // If a local branch with the same name exists, probably from a // previous MyPintMerge session, delete it. if (repo.Branches.Any(b => b.FriendlyName == localBranchName)) { DeleteBranch(repo, repo.Branches[localBranchName]); } // Create and check out the local branch. PrintMessage($"Checking out local branch {localBranchName} tracking remote branch {trackedBranch.FriendlyName}"); Branch localBranch = repo.CreateBranch(localBranchName, trackedBranch.Tip); Branch updatedBranch = repo.Branches.Update( localBranch, b => b.TrackedBranch = trackedBranch.CanonicalName); CheckoutOptions checkoutOptions = CreateCheckoutOptions(); checkoutCounter = 0; Commands.Checkout(repo, localBranch, checkoutOptions); // Cherry-pick to the currently checked out branch. PrintMessage($"Cherry-picking commit {sourceCommit.Sha} to local branch {updatedBranch.FriendlyName}"); try { var pickResult = repo.CherryPick(sourceCommit, sig, options); // Check the return value from the CherryPick method, // which can fail without throwing or sending a notification // to the callbacks. if (pickResult.Status == CherryPickStatus.Conflicts) { // If there are merge conflcts, exit. PrintMessage($"CONFLICT in local branch {updatedBranch.FriendlyName}, exiting."); return(ErrorCode); } } catch (EmptyCommitException ecex) { // Oddly, when there's nothing to do, i.e., when the commit // exists already in the tracked branch, libgit2sharp // throws an EmptyCommitException instead of reutrning // a CherryPickResult. PrintMessage($"No changes detected, no action taken in local branch {updatedBranch.FriendlyName}, continuing."); if (DeleteLocalBranches) { DeleteBranch(repo, localBranch); } continue; } catch (Exception ex) { PrintMessage($"Exception during cherry-pick {ex}, no action taken in local branch {updatedBranch.FriendlyName}, continuing."); //if (DeleteLocalBranches) //{ // DeleteBranch(repo, localBranch); //} continue; } // Prepare to push the changes to the tracked remote branch. // Assign the configuration options for the push. PushOptions pushOptions = CreatePushOptions(); // Push the branch to the remote repo. PrintMessage($"Pushing local branch {localBranchName} to remote {trackedBranch.FriendlyName}"); repo.Network.Push(localBranch, pushOptions); // Optionally, clean up by deleting the local branch. if (DeleteLocalBranches) { DeleteBranch(repo, localBranch); } } } return(SuccessCode); }