public void CallsCloneOnVsProvidedCloneService(bool recurseSubmodules, CloneOptions expectedCloneOptions)
        {
            var provider = Substitute.For<IUIProvider>();
            var gitRepositoriesExt = Substitute.For<IGitRepositoriesExt>();
            provider.GetService(typeof(IGitRepositoriesExt)).Returns(gitRepositoriesExt);
            var vsServices = new VSServices(provider);

            vsServices.Clone("https://github.com/github/visualstudio", @"c:\fake\ghfvs", recurseSubmodules);

            gitRepositoriesExt.Received()
                .Clone("https://github.com/github/visualstudio", @"c:\fake\ghfvs", expectedCloneOptions);
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Clone any object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceObject">The object to clone</param>
        /// <param name="options">Specify the Clone options</param>
        /// <returns></returns>
        public static T Clone <T>(this T sourceObject, CloneOptions options)
        {
            var cloneProvider = new CloneProvider <T>();

            return(cloneProvider.Clone(sourceObject, CloneConfiguration.CreateFromOptions(options)));
        }
Beispiel #4
0
        public static async Task ProcessMergeMessageAsync([QueueTrigger("merges")] Shared.Merge merge, TextWriter log)
        {
            var sessionId = Guid.NewGuid();

            var reposPath = new DirectoryInfo(ConfigurationManager.AppSettings["RepositoryPath"]).FullName;
            var repoPath  = Path.Combine(reposPath, merge.RepositoryName);

            await LogAsync($"Merge message received for commit '{merge.CommitId}'.", sessionId, log);

            var mergeSet = new MergeSet()
            {
                RepoName = merge.RepositoryName,
                RepoPath = repoPath,
                Changes  = new List <Node>()
            };

            var cloneOptions = new CloneOptions()
            {
                CredentialsProvider = (_url, _user, _cred) => GetRepoCredentials(merge.PersonalAccessToken)
            };

            if (!Directory.Exists(repoPath))
            {
                await LogAsync($"Repo path not found, creating directory '{repoPath}'.", sessionId, log);

                await LogAsync($"Cloning repository '{merge.RemoteUrl}'.", sessionId, log);

                Directory.CreateDirectory(repoPath);

                var cloneResult = Repository.Clone(merge.RemoteUrl, repoPath, cloneOptions);

                var files = Directory.GetFiles(repoPath, "*", SearchOption.AllDirectories);

                foreach (var file in files)
                {
                    var currentFileInfo = new FileInfo(file);

                    if (currentFileInfo.Directory.FullName.Replace(repoPath, "").ToLower().StartsWith("\\.git"))
                    {
                        continue;
                    }

                    mergeSet.Changes.Add(new Node()
                    {
                        Path   = file,
                        Status = ChangeKind.Added
                    });
                }
            }
            else
            {
                await LogAsync($"Pulling from repository '{merge.RemoteUrl}'.", sessionId, log);

                Directory.CreateDirectory(repoPath);

                using (var repo = new Repository(repoPath))
                {
                    PullOptions options = new PullOptions()
                    {
                        FetchOptions = new FetchOptions()
                        {
                            CredentialsProvider = new CredentialsHandler(
                                (url, usernameFromUrl, types) => GetRepoCredentials(merge.PersonalAccessToken))
                        }
                    };

                    var lastCommit = repo.Head.Tip;

                    var mergeResult = Commands.Pull(repo, GetRepoSignature(), options);

                    var headCommit = repo.Branches["origin/master"].Commits.First();

                    var treeChanges = repo.Diff.Compare <TreeChanges>(lastCommit.Tree, headCommit.Tree);

                    foreach (var treeChange in treeChanges)
                    {
                        if (treeChange.Status.Equals(ChangeKind.Renamed))
                        {
                            mergeSet.Changes.Add(new Node()
                            {
                                Path   = Path.Combine(repoPath, treeChange.OldPath),
                                Status = ChangeKind.Deleted
                            });
                        }
                        ;

                        mergeSet.Changes.Add(new Node()
                        {
                            Path   = Path.Combine(repoPath, treeChange.Path),
                            Status = treeChange.Status
                        });
                    }
                }
            }

            using (var repo = new Repository(repoPath))
            {
                mergeSet.Sha              = repo.Head.Tip.Sha;
                mergeSet.Author           = repo.Head.Tip.Author.Name;
                mergeSet.LastRevisionDate = repo.Head.Tip.Author.When;

                foreach (var change in mergeSet.Changes)
                {
                    change.RepoName = mergeSet.RepoName;
                    change.RepoPath = mergeSet.RepoPath;

                    change.Revisions.Add(new Revision()
                    {
                        Sha              = mergeSet.Sha,
                        Author           = mergeSet.Author,
                        LastRevisionDate = mergeSet.LastRevisionDate
                    });

                    if (change.Path.Replace(repoPath, "").ToLower().StartsWith("\\.git"))
                    {
                        continue;
                    }

                    await Helpers.QueueHelper.SendQueueMessage("renders", change);
                }
            }

            await Helpers.QueueHelper.SendQueueMessage("cleanups", mergeSet);
        }
Beispiel #5
0
        /// <summary>
        /// 重新设置整个表的所有 TreeIndex。
        /// 注意,此方法只保证生成的 TreeIndex 有正确的父子关系,同时顺序有可能被打乱。
        /// </summary>
        /// <param name="repository"></param>
        public static void ResetTreeIndex(EntityRepository repository)
        {
            using (var tran = RF.TransactionScope(repository))
            {
                //先清空
                var dp = repository.DataProvider as RdbDataProvider;
                if (dp == null)
                {
                    throw new InvalidProgramException("TreeIndexHelper.ResetTreeIndex 方法只支持在关系数据库上使用。");
                }
                var table  = dp.DbTable;
                var column = table.Columns.First(c => c.Info.Property == Entity.TreeIndexProperty);
                using (var dba = dp.CreateDbAccesser())
                {
                    dba.ExecuteText(string.Format("UPDATE {0} SET {1} = NULL", table.Name, column.Name));
                }

                var all = repository.GetAll();
                if (all.Count > 0)
                {
                    //如果加载的过程中,第一个节点刚好是根节点,
                    //则加载完成后是一棵完整的树,Index 也生成完毕,不需要再次处理。
                    if (all.IsTreeRootList)
                    {
                        all.ResetTreeIndex();
                        repository.Save(all);
                    }
                    else
                    {
                        var cloneOptions = CloneOptions.ReadSingleEntity();
                        var oldList      = new List <Entity>();
                        all.EachNode(e =>
                        {
                            var cloned = repository.New();
                            cloned.Clone(e, cloneOptions);
                            cloned.PersistenceStatus = PersistenceStatus.Unchanged;

                            oldList.Add(cloned);
                            return(false);
                        });

                        var newList = repository.NewList();
                        while (oldList.Count > 0)
                        {
                            foreach (var item in oldList)
                            {
                                var treePId = item.TreePId;
                                if (treePId == null)
                                {
                                    newList.Add(item);
                                    oldList.Remove(item);
                                    break;
                                }
                                else
                                {
                                    var parent = newList.EachNode(e => e.Id.Equals(treePId));
                                    if (parent != null)
                                    {
                                        parent.TreeChildren.LoadAdd(item);
                                        oldList.Remove(item);
                                        break;
                                    }
                                }
                            }
                        }
                        TreeHelper.MarkTreeFullLoaded(newList);
                        newList.ResetTreeIndex();
                        repository.Save(newList);
                    }
                }

                tran.Complete();
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        /// <summary>
        /// Get repository.
        /// </summary>
        /// <param name="latest">If true, ensure the repository is up to date.</param>
        /// <param name="reset">If true, the repository is cloned from scratch.</param>
        public Repository Init(bool latest, bool reset)
        {
            Validate();

            // special local path logic
            string workPath = ParseLocalUrl(RemoteUrl);

            if (workPath != null)
            {
                Repository local = null;
                if (FileUtility.IsFolderEmpty(workPath))
                {
                    local = new Repository(Repository.Init(workPath));
                }
                else
                {
                    local = new Repository(workPath);
                }

                // get latest from remote
                if (latest && local.Network.Remotes["origin"] != null)
                {
                    FetchOptions localFetchOptions = new FetchOptions();
                    localFetchOptions.CredentialsProvider += ProvideCredentials;

                    PullOptions pullOptions = new PullOptions();
                    pullOptions.FetchOptions = localFetchOptions;
                    local.Network.Pull(new Signature(AuthorName, AuthorEmail, DateTime.Now), pullOptions);
                }

                // get branch
                Branch branch = local.Branches[BranchName];
                if (branch == null)
                {
                    Branch remoteBranch = local.Branches[String.Format("origin/{0}", BranchName)];
                    if (remoteBranch != null)
                    {
                        branch = local.CreateBranch(BranchName, remoteBranch.Tip);
                        branch = local.Branches.Update(
                            branch,
                            b => b.TrackedBranch = remoteBranch.CanonicalName);
                    }
                }

                if (branch != null)
                {
                    local.Checkout(branch);
                }

                return(local);
            }

            // don't get latest or clone from remote
            if (!latest)
            {
                if (FileUtility.IsFolderEmpty(WorkingPath))
                {
                    throw new Exception("Repository doesn't exist.");
                }

                return(new Repository(WorkingPath));
            }

            Repository repo = null;

            // delete existing repository so we will start from scratch
            if (reset)
            {
                FileUtility.DeleteFolderContents(WorkingPath);
            }

            // clean out existing repository if it doesn't match current settings
            if (!FileUtility.IsFolderEmpty(WorkingPath))
            {
                repo = new Repository(WorkingPath);
                Remote remote = repo.Network.Remotes["origin"];
                if (remote == null || remote.Url != RemoteUrl)
                {
                    if (repo != null)
                    {
                        repo.Dispose();
                    }

                    repo = null;
                    FileUtility.DeleteFolderContents(WorkingPath);
                }
            }

            // clone repository if needed
            if (repo == null)
            {
                CloneOptions options = new CloneOptions();
                options.CredentialsProvider += ProvideCredentials;
                try
                {
                    repo = new Repository(Repository.Clone(RemoteUrl, WorkingPath, options));
                }
                finally
                {
                    options.CredentialsProvider -= ProvideCredentials;
                }
            }

            FetchOptions fetchOptions = null;

            try
            {
                // get latest changes
                fetchOptions = new FetchOptions();
                fetchOptions.CredentialsProvider += ProvideCredentials;

                PullOptions pullOptions = new PullOptions();
                pullOptions.FetchOptions = fetchOptions;
                repo.Network.Pull(new Signature(AuthorName, AuthorEmail, DateTime.Now), pullOptions);

                // get branch or create new one if needed
                Branch localBranch = repo.Branches[BranchName];
                if (localBranch == null)
                {
                    Branch remoteBranch = repo.Branches[String.Format("origin/{0}", BranchName)];
                    if (remoteBranch == null)
                    {
                        throw new Exception(String.Format("There is no branch named: {0} in the repository.", BranchName));
                    }

                    localBranch = repo.CreateBranch(BranchName, remoteBranch.Tip);
                    localBranch = repo.Branches.Update(
                        localBranch,
                        b => b.TrackedBranch = remoteBranch.CanonicalName);
                }

                // if the local branch is ahead of the remote branch then we need to start from scratch
                if (localBranch.TrackingDetails.AheadBy.HasValue &&
                    localBranch.TrackingDetails.AheadBy.Value > 0)
                {
                    if (!reset)
                    {
                        repo.Dispose();
                        return(Init(latest, true));
                    }

                    throw new Exception("It appears the local repository is out of sync with the remote repository.");
                }

                Branch = localBranch;

                // checkout branch and wipe out any uncommitted changes
                repo.Reset(ResetMode.Hard);
                CheckoutOptions checkoutOptions = new CheckoutOptions();
                checkoutOptions.CheckoutModifiers = CheckoutModifiers.Force;
                repo.Checkout(localBranch, checkoutOptions);
            }
            finally
            {
                if (fetchOptions != null)
                {
                    fetchOptions.CredentialsProvider -= ProvideCredentials;
                }
            }

            return(repo);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        private void DownloadAddon()
        {
            bool updated = false;
            bool cloned  = false;

            if (!Directory.Exists(info.packedPath))
            {
                Directory.CreateDirectory(info.packedPath);
            }

            if (Directory.Exists(info.dlPath) && Repository.IsValid(info.dlPath))
            {
                using (Repository repo = new Repository(info.dlPath))
                {
                    RepositoryStatus status = repo.RetrieveStatus();

                    string commit = repo.Head.Tip.Id.Sha;

                    // reset local changes
                    if (status.IsDirty)
                    {
                        repo.Reset(ResetMode.Hard);
                    }

                    // fetch & merge from origin
                    repo.Network.Fetch(repo.Network.Remotes["origin"]);
                    repo.MergeFetchedRefs(new Signature("meldii", "*****@*****.**", new DateTimeOffset()), new MergeOptions());

                    // updated
                    if (!repo.Head.Tip.Id.Sha.Equals(commit))
                    {
                        updated = true;
                    }
                }
            }
            else
            {
                if (Directory.Exists(info.dlPath))
                {
                    ForceDeleteDirectory(info.dlPath);
                }

                CloneOptions co = new CloneOptions();
                co.BranchName = info.branch;
                Repository.Clone(info.url, info.dlPath, co);
                updated = true;
                cloned  = true;
            }

            //Pack & ship it
            if (updated)
            {
                if (File.Exists(info.packedFile))
                {
                    File.Delete(info.packedFile);
                }

                ZipFile zip = new ZipFile(info.packedFile);
                foreach (string file in Directory.EnumerateFiles(info.dlPath, "*.*", SearchOption.AllDirectories))
                {
                    string rPath = file.Replace(info.dlPath, "").TrimStart(new char[] { '\\', '/' });
                    if (!rPath.StartsWith(".git", StringComparison.CurrentCultureIgnoreCase) && !rPath.Equals("README.md", StringComparison.CurrentCultureIgnoreCase))
                    {
                        string[] split   = rPath.Split(new char[] { '\\', '/' });
                        string   zipPath = split.Length == 1 ? "" : string.Join("\\", split, 0, split.Length - 1);

                        zip.AddFile(file, zipPath);
                    }
                }
                zip.Save();
            }

            if (cloned)
            {
                _Copy(Path.Combine(MeldiiSettings.Self.AddonLibaryPath, info.repoName) + ".zip", info.packedFile);
            }
        }
Beispiel #10
0
        public static bool GitDownload(ServerMod sm)
        {
            if (pulledGits.Contains(sm.GitUrl.ToLower()))
            {
                return(true);
            }

            pulledGits.Add(sm.GitUrl.ToLower());

            Console.WriteLine("");
            Console.WriteLine("Pulling from git...");

            try {
                string token = sm.GitToken.Replace("token ", "");

                string gitName = Path.GetFileNameWithoutExtension(sm.GitUrl);
                string gitPath = Path.Combine(Program.Settings.GitDirectory, gitName);

                if (!Directory.Exists(Program.Settings.GitDirectory))
                {
                    Directory.CreateDirectory(Program.Settings.GitDirectory);
                }

                // This options allows you to use the SSH option. (Allows for Repo specific auth)
                if (sm.GitType == 3)
                {
                    if (Directory.Exists(gitPath))
                    {
                        return(true);
                    }

                    string branch = "";

                    if (sm.GitPath != "")
                    {
                        branch = $" -b {sm.GitPath}";
                    }

                    Process.Start(new ProcessStartInfo
                    {
                        WorkingDirectory = Program.Settings.GitDirectory,
                        FileName         = "git",
                        Arguments        = $"clone --depth=1{branch} {sm.GitUrl}",
                        UseShellExecute  = false,
                        CreateNoWindow   = true
                    }).WaitForExit();

                    Program.DeleteDirectory(Path.Combine(Program.Settings.GitDirectory, gitName, ".git"));

                    return(true);
                }


                if (Directory.Exists(Path.Combine(Program.Settings.GitDirectory, sm.GitPath)))
                {
                    Directory.Delete(Program.Settings.GitDirectory, true);
                }
                Directory.CreateDirectory(Program.Settings.GitDirectory);

                if (sm.GitType == 2)
                {
                    CloneOptions co = new CloneOptions
                    {
                        CredentialsProvider = (_url, _user, _cred) =>
                                              new UsernamePasswordCredentials
                        {
                            Username = "******",
                            Password = sm.GitToken
                        }
                    };
                    if (sm.GitPath != "")
                    {
                        co.BranchName = sm.GitPath;
                    }
                    Repository.Clone(sm.GitUrl, gitPath, co);
                }
                else
                {
                    CloneOptions co = new CloneOptions
                    {
                        CredentialsProvider = (_url, _user, _cred) =>
                                              new UsernamePasswordCredentials
                        {
                            Username = sm.GitToken,
                            Password = string.Empty
                        }
                    };
                    if (sm.GitPath != "")
                    {
                        co.BranchName = sm.GitPath;
                    }
                    Repository.Clone(sm.GitUrl, gitPath, co);
                }

                return(true);
            } catch (Exception ex) {
                Console.WriteLine("Error in download: " + ex);
                return(false);
            }
        }
Beispiel #11
0
 public void Clone(string url, string branch, IFolder folder, CloneOptions cloneOptions, bool useCache, IErrorsAndInfos errorsAndInfos)
 {
     Clone(url, branch, folder, cloneOptions, useCache, () => true, () => { }, errorsAndInfos);
 }
Beispiel #12
0
        static async Task Main(string[] args)
        {
            Uri    org1Url  = new Uri("https://dev.azure.com/" + Environment.GetEnvironmentVariable("ORG1"));
            String project1 = Environment.GetEnvironmentVariable("PROJ1");
            String pat1     = Environment.GetEnvironmentVariable("PAT1"); // See https://docs.microsoft.com/azure/devops/integrate/get-started/authentication/pats

            Uri    org2Url  = new Uri("https://dev.azure.com/" + Environment.GetEnvironmentVariable("ORG2"));
            String project2 = Environment.GetEnvironmentVariable("PROJ2");
            String pat2     = Environment.GetEnvironmentVariable("PAT2");

            // Project name which this should look at
            Boolean dryRun = !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("DRYRUN"));

            // Create a connection
            var sourceConnection      = new VssConnection(org1Url, new VssBasicCredential(string.Empty, pat1));
            var destinationConnection = new VssConnection(org2Url, new VssBasicCredential(string.Empty, pat2));

            var destProject = await destinationConnection.GetClient <ProjectHttpClient>().GetProject(project2);


            var sourceRepos = await GetAllRepos(sourceConnection, project1);

            var destReposDict = (await GetAllRepos(destinationConnection, project2)).ToDictionary(x => x.Name);

            var missingReposInDest = sourceRepos.Where(x => !destReposDict.ContainsKey(getDestNameFromSourceName(x.Name)));

            var tempPath = Path.GetTempPath();
            var tempDir  = Directory.CreateDirectory(Path.Join(tempPath, "repocloner", RandomString(5).ToLower()));

            Console.WriteLine($"Using path {tempDir.FullName}");

            // Create any repos missing in proj2
            var destSourceClient = destinationConnection.GetClient <GitHttpClient>();

            foreach (var sourceRepo in missingReposInDest)
            {
                if (dryRun)
                {
                    Console.WriteLine($"Would create repo {sourceRepo.Name} in {destSourceClient.BaseAddress}");
                }
                else
                {
                    var gitToCreate = new GitRepositoryCreateOptions()
                    {
                        Name             = getDestNameFromSourceName(sourceRepo.Name),
                        ProjectReference = destProject,
                    };
                    var destRepo = await destSourceClient.CreateRepositoryAsync(gitToCreate);

                    destReposDict[destRepo.Name] = destRepo;
                }
            }

            // Sync source from proj1 to proj2 for all branchs
            foreach (var sourceRepo in sourceRepos)
            {
                var destRepo = destReposDict[getDestNameFromSourceName(sourceRepo.Name)];
                if (dryRun)
                {
                    Console.WriteLine($"Would clone {sourceRepo.Name} @ {sourceRepo.WebUrl} and sync to {destRepo.Name} @ {destRepo.WebUrl}");
                }
                else
                {
                    // Create a temp dir to store the cloned repo
                    var gitDir = Directory.CreateDirectory(Path.Join(tempDir.FullName, sourceRepo.Name));

                    var co = new CloneOptions();
                    CredentialsHandler sourceCredProvider = (_url, _user, _cred) => new UsernamePasswordCredentials {
                        Username = pat1, Password = pat1
                    };
                    co.CredentialsProvider = sourceCredProvider;


                    Console.WriteLine($"Cloning source {sourceRepo.Name}");
                    Repository.Clone(sourceRepo.RemoteUrl, gitDir.FullName, co);

                    using (var repo = new Repository(gitDir.FullName))
                    {
                        CredentialsHandler destCredProvider = (_url, _user, _cred) => new UsernamePasswordCredentials {
                            Username = pat2, Password = pat2
                        };
                        LibGit2Sharp.PushOptions options = new LibGit2Sharp.PushOptions();
                        options.CredentialsProvider = destCredProvider;

                        if (!repo.Network.Remotes.Where(x => x.Name == "dest").Any())
                        {
                            repo.Network.Remotes.Add("dest", destRepo.RemoteUrl);
                        }
                        else
                        {
                            repo.Network.Remotes.Remove("dest");
                            repo.Network.Remotes.Add("dest", destRepo.RemoteUrl);
                        }

                        var destRemote = repo.Network.Remotes["dest"];

                        foreach (var branch in repo.Branches)
                        {
                            Console.WriteLine($"Pusing source {sourceRepo.Name}:{branch} to {destRepo.Name}:{branch} @ {destRepo.Url}");

                            repo.Network.Push(destRemote, branch.CanonicalName, new PushOptions()
                            {
                                CredentialsProvider = destCredProvider
                            });
                        }
                    }
                }
            }
        }
Beispiel #13
0
            /// <summary>
            /// 复制一个指定的对象
            /// 包括所有的孩子(如果是树节点的话),所有的实体属性和细表属性。
            /// </summary>
            /// <param name="oldObject">需要复制的对象</param>
            /// <param name="parentNode">如果不为null,表示需要设置新的对象成为这个对象的孩子</param>
            /// <param name="modifyName">是否在这个对象的Name属性上添加“-新增”</param>
            /// <returns></returns>
            private Entity CopyObject(Entity oldObject, Entity parentNode, bool modifyName, CloneOptions options)
            {
                throw new NotImplementedException();//huqf
                ////添加一个新的空对象
                //Entity newObject = null;
                //if (parentNode != null)
                //{
                //    newObject = this.NewObject(parentNode, true);
                //}
                //else
                //{
                //    newObject = this.NewObject(oldObject, false);
                //}

                //try
                //{
                //    newObject.BeforeCopy();

                //    if (this.IsDealingTree)
                //    {
                //        var newNode = newObject;
                //        //暂存ParentNode
                //        Entity cachedParent = null;
                //        cachedParent = newNode.TreeParentEntity;

                //        //暂存OrderNo
                //        int oldOrderNo = newObject.OrderNo;

                //        //拷贝所有属性值
                //        newObject.Clone(oldObject, options);

                //        newNode.TreeParentEntity = cachedParent;

                //        //还原OrderNo
                //        newObject.OrderNo = oldOrderNo;

                //        //拷贝所有的孩子
                //        var children = oldObject.ChildrenNodes;
                //        for (int i = 0, c = children.Count; i < c; i++)
                //        {
                //            var oldChild = children[i] as Entity;
                //            //复制一个新的节点作为newObject的孩子
                //            var newChild = this.CopyObject(oldChild, newNode, false, options);
                //        }
                //    }
                //    else
                //    {
                //        //拷贝所有属性值
                //        newObject.Clone(oldObject, options);
                //    }

                //    this.TryModifyName(newObject, modifyName);
                //}
                //finally
                //{
                //    newObject.AfterCopy();
                //}

                //return newObject;
            }
 public async Task <string> Clone(string url, string workingDirectory, CloneOptions options = null)
 {
     return(await new Task <string>(() => Repository.Clone(url, workingDirectory, options)));
 }
        protected virtual void HandleAutoVersioning(Repository myRepository, string myShortName, Dependency dependency, CloneOptions cloneOptions)
        {
            if (!string.IsNullOrEmpty(dependency.Commit))
            {
                throw new InvalidOperationException($"Dependency {dependency}: autoversioning: definition is incoherent: Branch = '{dependency.Branch}' and a Commit = '{dependency.Commit}' => you can't have both set!");
            }

            if (Directory.Exists(dependency.OutputFolder))
            {
                Log($"Dependency {dependency}: autoversioning: output folder already exists: removing...");
                new DirectoryInfo(dependency.OutputFolder).ForceDelete();
            }

            Log($"Dependency {dependency}: autoversioning: cloning default branch of '{dependency.Remote}' into '{dependency.OutputFolder}'");
            Repository.Clone(dependency.Remote, dependency.OutputFolder, cloneOptions);

            try
            {
                IndentLevel++;

                using (var otherRepository = new Repository(dependency.OutputFolder))
                {
                    otherRepository.CheckoutAllRemoteBranches();
                    VersionResolver.CheckoutBranchInDependencyRepository(otherRepository, myRepository, myShortName, this);
                }
            }
            finally
            {
                IndentLevel--;
            }
        }
Beispiel #16
0
            /// <summary>
            /// 复制一个指定的对象
            /// 包括所有的孩子(如果是树节点的话),所有的实体属性和细表属性。
            /// </summary>
            /// <param name="oldObject">需要复制的对象</param>
            /// <param name="parentNode">如果不为null,表示需要设置新的对象成为这个对象的孩子</param>
            /// <param name="modifyName">是否在这个对象的Name属性上添加“-新增”</param>
            /// <returns></returns>
            private Entity CopyObject(Entity oldObject, Entity parentNode, bool modifyName, CloneOptions options)
            {
                throw new NotImplementedException();//huqf
                ////添加一个新的空对象
                //Entity newObject = null;
                //if (parentNode != null)
                //{
                //    newObject = this.NewObject(parentNode, true);
                //}
                //else
                //{
                //    newObject = this.NewObject(oldObject, false);
                //}

                //try
                //{
                //    newObject.BeforeCopy();

                //    if (this.IsDealingTree)
                //    {
                //        var newNode = newObject;
                //        //暂存ParentNode
                //        Entity cachedParent = null;
                //        cachedParent = newNode.TreeParentEntity;

                //        //暂存OrderNo
                //        int oldOrderNo = newObject.OrderNo;

                //        //拷贝所有属性值
                //        newObject.Clone(oldObject, options);

                //        newNode.TreeParentEntity = cachedParent;

                //        //还原OrderNo
                //        newObject.OrderNo = oldOrderNo;

                //        //拷贝所有的孩子
                //        var children = oldObject.ChildrenNodes;
                //        for (int i = 0, c = children.Count; i < c; i++)
                //        {
                //            var oldChild = children[i] as Entity;
                //            //复制一个新的节点作为newObject的孩子
                //            var newChild = this.CopyObject(oldChild, newNode, false, options);
                //        }
                //    }
                //    else
                //    {
                //        //拷贝所有属性值
                //        newObject.Clone(oldObject, options);
                //    }

                //    this.TryModifyName(newObject, modifyName);
                //}
                //finally
                //{
                //    newObject.AfterCopy();
                //}

                //return newObject;
            }
        private void MigrateRepository(Repository repository, Octokit.Repository githubRepo)
        {
            var clonePath = Path.Combine(_configuration.TempPath, repository.RepositoryName);

            if (Directory.Exists(clonePath) && (Directory.GetFiles(clonePath).Length > 0 ||
                                                Directory.GetDirectories(clonePath).Length > 0))
            {
                using var localRepo = new LibGit2Sharp.Repository(clonePath);
                Policy
                .Handle <LibGit2SharpException>(exception => exception.Message.Contains("Secure"))
                .WaitAndRetry(2, retryAttempt =>
                              TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                              )
                .Execute(() =>
                {
                    Log.Information("Pushing to github");
                    localRepo.Network.Push(localRepo.Branches, new PushOptions
                    {
                        CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials
                        {
                            Username = _configuration.GithubUsername,
                            Password = _configuration.GithubToken
                        },
                    });
                });
            }
            else
            {
                var cloneOptions = new CloneOptions
                {
                    CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials
                    {
                        Username = _configuration.BitbucketUsername,
                        Password = _configuration.BitbucketPassword
                    },
                };

                Policy
                .Handle <LibGit2SharpException>(exception => exception.Message.Contains("Secure"))
                .WaitAndRetry(5, retryAttempt =>
                              TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                              ).Execute(() =>
                {
                    Log.Information("Cloning from Bitbucket");
                    return(LibGit2Sharp.Repository.Clone(repository.CloneUrl.ToString(), clonePath, cloneOptions));
                });

                using var localRepo = new LibGit2Sharp.Repository(clonePath);
                localRepo.Network.Remotes.Remove("origin");
                var newRemote = localRepo.Network.Remotes.Add("origin", githubRepo.CloneUrl);

                foreach (var localRepoBranch in localRepo.Branches)
                {
                    localRepo.Branches.Update(localRepoBranch,
                                              b => b.Remote         = newRemote.Name,
                                              b => b.UpstreamBranch = localRepoBranch.CanonicalName);
                }

                Policy
                .Handle <LibGit2SharpException>(exception => exception.Message.Contains("Secure"))
                .WaitAndRetry(5, retryAttempt =>
                              TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                              )
                .Execute(() =>
                {
                    Log.Information("Pushing to github");
                    localRepo.Network.Push(localRepo.Branches, new PushOptions
                    {
                        CredentialsProvider = (url, user, cred) => new UsernamePasswordCredentials
                        {
                            Username = _configuration.GithubUsername,
                            Password = _configuration.GithubToken
                        },
                    });
                });
            }
        }
Beispiel #18
0
        /// <inheritdoc />
        public async Task <IRepository> CloneRepository(
            Uri url,
            string initialBranch,
            string username,
            string password,
            Action <int> progressReporter,
            bool recurseSubmodules,
            CancellationToken cancellationToken)
        {
            if (url == null)
            {
                throw new ArgumentNullException(nameof(url));
            }
            if (progressReporter == null)
            {
                throw new ArgumentNullException(nameof(progressReporter));
            }

            logger.LogInformation("Begin clone {0} (Branch: {1})", url, initialBranch);
            lock (semaphore)
            {
                if (CloneInProgress)
                {
                    throw new JobException(ErrorCode.RepoCloning);
                }
                CloneInProgress = true;
            }

            try
            {
                using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
                {
                    logger.LogTrace("Semaphore acquired");
                    var repositoryPath = ioManager.ResolvePath();
                    if (!await ioManager.DirectoryExists(repositoryPath, cancellationToken).ConfigureAwait(false))
                    {
                        try
                        {
                            var cloneOptions = new CloneOptions
                            {
                                OnProgress         = (a) => !cancellationToken.IsCancellationRequested,
                                OnTransferProgress = (a) =>
                                {
                                    var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
                                    progressReporter((int)percentage);
                                    return(!cancellationToken.IsCancellationRequested);
                                },
                                RecurseSubmodules           = recurseSubmodules,
                                OnUpdateTips                = (a, b, c) => !cancellationToken.IsCancellationRequested,
                                RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
                                BranchName          = initialBranch,
                                CredentialsProvider = repositoryFactory.GenerateCredentialsHandler(username, password)
                            };

                            await repositoryFactory.Clone(
                                url,
                                cloneOptions,
                                repositoryPath,
                                cancellationToken)
                            .ConfigureAwait(false);
                        }
                        catch
                        {
                            try
                            {
                                logger.LogTrace("Deleting partially cloned repository...");

                                // DCT: Cancellation token is for job, operation must run regardless
                                await ioManager.DeleteDirectory(repositoryPath, default).ConfigureAwait(false);
                            }
                            catch (Exception e)
                            {
                                logger.LogDebug(e, "Error deleting partially cloned repository!");
                            }

                            throw;
                        }
                    }
                    else
                    {
                        logger.LogDebug("Repository exists, clone aborted!");
                        return(null);
                    }
                }

                logger.LogInformation("Clone complete!");
            }
            finally
            {
                CloneInProgress = false;
            }

            return(await LoadRepository(cancellationToken).ConfigureAwait(false));
        }
Beispiel #19
0
        public void CanRecursivelyCloneSubmodules()
        {
            var    uri = new Uri($"file://{Path.GetFullPath(SandboxSubmoduleSmallTestRepo())}");
            var    scd = BuildSelfCleaningDirectory();
            string relativeSubmodulePath = "submodule_target_wd";

            // Construct the expected URL the submodule will clone from.
            string expectedSubmoduleUrl = Path.Combine(Path.GetDirectoryName(uri.AbsolutePath), relativeSubmodulePath);

            expectedSubmoduleUrl = expectedSubmoduleUrl.Replace('\\', '/');

            Dictionary <string, CloneCallbackInfo> callbacks = new Dictionary <string, CloneCallbackInfo>();

            CloneCallbackInfo currentEntry  = null;
            bool unexpectedOrderOfCallbacks = false;

            CheckoutProgressHandler checkoutProgressHandler = (x, y, z) =>
            {
                if (currentEntry != null)
                {
                    currentEntry.CheckoutProgressCalled = true;
                }
                else
                {
                    // Should not be called if there is not a current
                    // callbackInfo entry.
                    unexpectedOrderOfCallbacks = true;
                }
            };

            UpdateTipsHandler remoteRefUpdated = (x, y, z) =>
            {
                if (currentEntry != null)
                {
                    currentEntry.RemoteRefUpdateCalled = true;
                }
                else
                {
                    // Should not be called if there is not a current
                    // callbackInfo entry.
                    unexpectedOrderOfCallbacks = true;
                }

                return(true);
            };

            RepositoryOperationStarting repositoryOperationStarting = (x) =>
            {
                if (currentEntry != null)
                {
                    // Should not be called if there is a current
                    // callbackInfo entry.
                    unexpectedOrderOfCallbacks = true;
                }

                currentEntry = new CloneCallbackInfo();
                currentEntry.StartingWorkInRepositoryCalled = true;
                currentEntry.RecursionDepth = x.RecursionDepth;
                currentEntry.RemoteUrl      = x.RemoteUrl;
                callbacks.Add(x.RepositoryPath, currentEntry);

                return(true);
            };

            RepositoryOperationCompleted repositoryOperationCompleted = (x) =>
            {
                if (currentEntry != null)
                {
                    currentEntry.FinishedWorkInRepositoryCalled = true;
                    currentEntry = null;
                }
                else
                {
                    // Should not be called if there is not a current
                    // callbackInfo entry.
                    unexpectedOrderOfCallbacks = true;
                }
            };

            CloneOptions options = new CloneOptions()
            {
                RecurseSubmodules            = true,
                OnCheckoutProgress           = checkoutProgressHandler,
                OnUpdateTips                 = remoteRefUpdated,
                RepositoryOperationStarting  = repositoryOperationStarting,
                RepositoryOperationCompleted = repositoryOperationCompleted,
            };

            string clonedRepoPath = Repository.Clone(uri.AbsolutePath, scd.DirectoryPath, options);
            string workDirPath;

            using (Repository repo = new Repository(clonedRepoPath))
            {
                workDirPath = repo.Info.WorkingDirectory.TrimEnd(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar });
            }

            // Verification:
            // Verify that no callbacks were called in an unexpected order.
            Assert.False(unexpectedOrderOfCallbacks);

            Dictionary <string, CloneCallbackInfo> expectedCallbackInfo = new Dictionary <string, CloneCallbackInfo>();

            expectedCallbackInfo.Add(workDirPath, new CloneCallbackInfo()
            {
                RecursionDepth = 0,
                RemoteUrl      = uri.AbsolutePath,
                StartingWorkInRepositoryCalled = true,
                FinishedWorkInRepositoryCalled = true,
                CheckoutProgressCalled         = true,
                RemoteRefUpdateCalled          = true,
            });

            expectedCallbackInfo.Add(Path.Combine(workDirPath, relativeSubmodulePath), new CloneCallbackInfo()
            {
                RecursionDepth = 1,
                RemoteUrl      = expectedSubmoduleUrl,
                StartingWorkInRepositoryCalled = true,
                FinishedWorkInRepositoryCalled = true,
                CheckoutProgressCalled         = true,
                RemoteRefUpdateCalled          = true,
            });

            // Callbacks for each expected repository that is cloned
            foreach (KeyValuePair <string, CloneCallbackInfo> kvp in expectedCallbackInfo)
            {
                CloneCallbackInfo entry = null;
                Assert.True(callbacks.TryGetValue(kvp.Key, out entry), string.Format("{0} was not found in callbacks.", kvp.Key));

                Assert.Equal(kvp.Value.RemoteUrl, entry.RemoteUrl);
                Assert.Equal(kvp.Value.RecursionDepth, entry.RecursionDepth);
                Assert.Equal(kvp.Value.StartingWorkInRepositoryCalled, entry.StartingWorkInRepositoryCalled);
                Assert.Equal(kvp.Value.FinishedWorkInRepositoryCalled, entry.FinishedWorkInRepositoryCalled);
                Assert.Equal(kvp.Value.CheckoutProgressCalled, entry.CheckoutProgressCalled);
                Assert.Equal(kvp.Value.RemoteRefUpdateCalled, entry.RemoteRefUpdateCalled);
            }

            // Verify the state of the submodule
            using (Repository repo = new Repository(clonedRepoPath))
            {
                var sm = repo.Submodules[relativeSubmodulePath];
                Assert.True(sm.RetrieveStatus().HasFlag(SubmoduleStatus.InWorkDir |
                                                        SubmoduleStatus.InConfig |
                                                        SubmoduleStatus.InIndex |
                                                        SubmoduleStatus.InHead));

                Assert.NotNull(sm.HeadCommitId);
                Assert.Equal("480095882d281ed676fe5b863569520e54a7d5c0", sm.HeadCommitId.Sha);

                Assert.False(repo.RetrieveStatus().IsDirty);
            }
        }
        public void Process(ScheduledTaskContext context)
        {
            if (context.Task.TaskType == TaskType)
            {
                var settings = this.orchardServices.WorkContext.CurrentSite.As <GITSettingsPart>();
                if (string.IsNullOrEmpty(settings.Server))
                {
                    return;
                }

                try
                {
                    this.transactionManager.Demand();
                    var gitPath = this.appDataFolder.Combine("Sites", shellSettings.Name, "GIT");
                    if (!this.appDataFolder.DirectoryExists(gitPath))
                    {
                        this.appDataFolder.CreateDirectory(gitPath);
                    }

                    var serverRecord = this.svnServerRepository.Table.FirstOrDefault(c => c.Server == settings.Server);

                    var        path       = Path.Combine(gitPath, settings.LocalFolder);
                    var        mappedPath = this.appDataFolder.MapPath(path);
                    Repository repo       = null;
                    if (serverRecord == null)
                    {
                        if (this.appDataFolder.DirectoryExists(path))
                        {
                            Directory.Delete(mappedPath, true);
                        }

                        this.appDataFolder.CreateDirectory(path);
                        // var destination = Repository.Init(mappedPath);
                        CloneOptions options = new CloneOptions();
                        options.CredentialsProvider = new LibGit2Sharp.Handlers.CredentialsHandler(
                            (url, usernameFromUrl, types) => new UsernamePasswordCredentials()
                        {
                            Username = settings.Username,
                            Password = settings.Password
                        });
                        Repository.Clone(settings.Server, mappedPath, options);
                        repo = new Repository(mappedPath);

                        serverRecord = new GITServerRecord {
                            Server = settings.Server, LastRevision = settings.LastRevision, FromDate = DateTime.UtcNow
                        };
                        this.svnServerRepository.Create(serverRecord);
                        this.svnServerRepository.Flush();
                    }

                    repo = repo ?? new Repository(mappedPath);
                    var branches = !string.IsNullOrEmpty(settings.Branches) ? settings.Branches.Split(',') : new[] { "master" };
                    branches = branches.Select(c => c.Trim()).Where(c => !string.IsNullOrEmpty(c)).ToArray();

                    if (string.IsNullOrEmpty(settings.Password) || string.IsNullOrEmpty(settings.Username))
                    {
                        repo.Network.Fetch("origin", branches.Select(c => c + ":" + c));
                    }
                    else
                    {
                        FetchOptions options = new FetchOptions();
                        options.CredentialsProvider = new LibGit2Sharp.Handlers.CredentialsHandler(
                            (url, usernameFromUrl, types) => new UsernamePasswordCredentials()
                        {
                            Username = settings.Username,
                            Password = settings.Password
                        });
                        repo.Network.Fetch("origin", branches.Select(c => c + ":" + c), options);
                    }

                    var branchRecords = this.gitServerBranchRepository.Table.Where(c => c.ServerRecord.Id == serverRecord.Id).ToList();

                    foreach (var branchName in branches)
                    {
                        var branch = repo.Branches.FirstOrDefault(c => c.FriendlyName == branchName);
                        if (branch == null)
                        {
                            continue;
                        }

                        var branchRecord = branchRecords.FirstOrDefault(c => c.BranchName == branchName);
                        if (branchRecord == null)
                        {
                            branchRecord = new GITServerBranchRecord {
                                BranchName = branchName, ServerRecord = serverRecord, LastUpdate = DateTime.UtcNow
                            };
                            this.gitServerBranchRepository.Create(branchRecord);
                            this.gitServerBranchRepository.Flush();
                        }

                        var commits = branch.Commits.ToList();
                        if (!string.IsNullOrEmpty(branchRecord.Sha))
                        {
                            var commit = commits.FirstOrDefault(c => c.Sha == branchRecord.Sha);
                            if (commit != null)
                            {
                                int index = commits.IndexOf(commit);
                                commits = commits.Skip(index + 1).ToList();
                            }
                        }

                        foreach (var commit in commits)
                        {
                            RaiseWorkflow(branchRecord, commit);
                        }
                    }

                    var settingContentItem = this.orchardServices.ContentManager.Get(settings.Id);
                    var gitSettingPart     = settingContentItem.As <GITSettingsPart>();
                    gitSettingPart.LastSuccessfullConnectionTime = DateTime.UtcNow;
                    gitSettingPart.LatestError     = null;
                    gitSettingPart.LatestErrorTime = null;
                    this.transactionManager.Demand();
                }
                catch (Exception e)
                {
                    this.transactionManager.Cancel();

                    this.Logger.Error(e, e.Message);

                    // We need a new transaction for storing the data
                    this.transactionManager.RequireNew();
                    settings.LatestError     = e.Message;
                    settings.LatestErrorTime = DateTime.UtcNow;
                    var settingContentItem = this.orchardServices.ContentManager.Get(settings.Id);
                    var gitSettingPart     = settingContentItem.As <GITSettingsPart>();
                    gitSettingPart.LatestError     = e.Message;
                    gitSettingPart.LatestErrorTime = settings.LatestErrorTime;
                    this.transactionManager.Demand();
                }
                finally
                {
                    DateTime nextTaskDate = DateTime.UtcNow.AddMinutes(PeriodInMinutes);
                    this.ScheduleNextTask(nextTaskDate);
                }
            }
        }
        public List <Commit> Get(String path, String username, String password, String branch)
        {
            DirectoryInfo di = new DirectoryInfo("tempRepo/");

            if (di.Exists)
            {
                BranchController.setAttributesNormal(di);
                di.Delete(true);
            }
            string clone;

            if (username != null && password != null)
            {
                var cloneOptions = new CloneOptions()
                {
                    CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials
                    {
                        Username = username,
                        Password = password
                    }
                };
                clone = Repository.Clone(path, "tempRepo/", cloneOptions);
            }
            else
            {
                clone = Repository.Clone(path, "tempRepo/");
            }
            var list = new List <Commit>();

            using (var repo = new Repository(@clone))
            {
                // Object lookup
                var obj    = repo.Lookup("sha");
                var commit = repo.Lookup <LibGit2Sharp.Commit>("sha");
                var tree   = repo.Lookup <Tree>("sha");
                // var tag = repo.Lookup<Tag>("sha");

                ICommitLog commits = null;

                if (branch == null)
                {
                    commits = repo.Head.Commits;
                }
                else
                {
                    commits = repo.Branches[branch].Commits;
                }

                foreach (var tempCommit in commits.Take(100))
                {
                    string message;
                    string type = "None";
                    if (tempCommit.Message.Contains(":"))
                    {
                        string[] strings = tempCommit.Message.Split(":");
                        message = strings[1];
                        type    = strings[0];
                    }
                    else
                    {
                        message = tempCommit.Message;
                    }

                    var commitObj = new Commit
                    {
                        author = tempCommit.Author, commiter = tempCommit.Committer, message = message, type = type
                    };
                    list.Add(commitObj);
                }

                return(list);

                // Branches
                // special kind of reference
            }
        }
Beispiel #22
0
        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 (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
            if (isWikiCompress == 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);
            }

            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);

            // 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
            {
                repo.Network.Push(remote, $"refs/heads/{KnownGitHubs.BranchName}", new PushOptions
                {
                    CredentialsProvider = credentialsProvider,
                });
            }

            return(true);
        }
Beispiel #23
0
        private static void Main(string[] args)
        {
            var result = CommandLine.Parser.Default.ParseArguments <Options>(args);

            if (!result.Errors.Any())
            {
                string url = result.Value.Repository;

                var brancOption    = result.Value.Branch;
                var branchSepIndex = brancOption.IndexOf('/');
                if (branchSepIndex > 0)
                {
                    var credentials = new UsernamePasswordCredentials
                    {
                        Username = result.Value.UserName,
                        Password = result.Value.Password
                    };
                    CredentialsHandler credHandler = (s, fromUrl, types) => credentials;

                    var remote = brancOption.Substring(0, branchSepIndex);
                    var branch = brancOption.Substring(branchSepIndex + 1, brancOption.Length - branchSepIndex - 1);

                    var workingDirectory = result.Value.LocalRepoPath;

                    var isLocalRepoExist = Repository.Discover(workingDirectory);
                    if (isLocalRepoExist == null)
                    {
                        var cloneOptions = new CloneOptions {
                            CredentialsProvider = credHandler
                        };
                        Repository.Clone(url, workingDirectory, cloneOptions);
                    }

                    Repository repo = null;
                    try
                    {
                        var tagName = result.Value.TagName;
                        repo = new Repository(workingDirectory);
                        //repo.Fetch(remote, new FetchOptions(){CredentialsProvider = credHandler});
                        repo.Network.Pull(new Signature(result.Value.UserName, result.Value.Email, new DateTimeOffset()),
                                          new PullOptions()
                        {
                            FetchOptions = new FetchOptions()
                            {
                                CredentialsProvider = credHandler
                            }
                        });
                        repo.ApplyTag(tagName);
                        PushChanges(repo, credHandler, remote, branch, tagName);
                        Console.WriteLine("Tagged :{0}", result.Value.TagName);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Error happened {0}", ex.Message);
                    }
                    finally
                    {
                        if (repo != null)
                        {
                            repo.Dispose();
                        }
                    }
                }
            }
            Console.ReadLine();
        }
Beispiel #24
0
        internal void InitRepository(string path, RepositoryConfig config)
        {
            this.config = config;
            Logger.Write("Initializing Repository.");
            _repoBase = path;
            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }

            if (Directory.Exists(path + Path.DirectorySeparatorChar + ".git"))
            {
                Logger.Write("Repository found, opening.");
                /* already a git repo */
                _repository = new Repository(_repoBase);
            }
            else
            {
                if (config.Url.Length > 0)
                {
                    Logger.Write("Repository URL is set, cloning repo to disk.");
                    /* repository is configured with a remote, try cloning from there */
                    try
                    {
                        var co = new CloneOptions();
                        co.CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials {
                            Username = config.User, Password = config.Password
                        };
                        var result = Repository.Clone(config.Url, _repoBase, co);
                    } catch (Exception ex)
                    {
                        /* Cloning failed, maybe it doesn't exist at the remote yet. Gitlab lets you push to a non-existant repo to create it, so we should continue */
                        Logger.Write("Failed to clone repo, creating new repository.");
                        Repository.Init(_repoBase);
                    }
                }
                else
                {
                    Repository.Init(_repoBase);
                }
                _repository = new Repository(_repoBase);
            }

            /* confirm this repository has an "origin" remote */
            if (_repository.Network.Remotes["origin"] != null)
            {
                /* there is an origin, make sure it points to the URL in config */
                if (_repository.Network.Remotes["origin"].Url.Equals(config.Url) == false)
                {
                    Logger.Write("Repository origin doesn't match config. Updating...");
                    _repository.Network.Remotes.Update("origin", r => r.Url = config.Url);
                }
            }
            else
            {
                Logger.Write("Repository doesn't have an origin. Adding...");
                /* no origin, lets set one if we have a URL */
                if (config.Url.Length > 0)
                {
                    _repository.Network.Remotes.Add("origin", config.Url);
                }
            }

            /* confirm .gitignore is present */
            var gitAttrFile = Path.Join(_repoBase, ".gitattributes");

            if (File.Exists(gitAttrFile) == false)
            {
                Logger.Write("Repository does not have a gitattributes present. Adding...");
                File.WriteAllText(gitAttrFile, "* text eol=crlf");
                Commands.Stage(_repository, gitAttrFile);

                Signature author    = new Signature("PIVET", "PIVET", DateTime.Now);
                Signature committer = author;
                Commit    commit    = _repository.Commit("Added gitattributes for consistent line endings", author, committer);
            }
        }
Beispiel #25
0
 public string Clone(string sourceUrl, string workdirPath, CloneOptions options)
 => Repository.Clone(sourceUrl, workdirPath, options);
Beispiel #26
0
        public static Repository PrepareRepository(
            string repositoryDescriptor,
            string descriptorIsFor,
            bool allowEmpty,
            bool allowRemote,
            int maxDepth,
            string mustLocalTailingMessage  = "",
            string mustExistsTailingMessage = "")
        {
            string repositoryPath;

#if SUPPORT_REMOTE_REPOSITORY
            if (UrlSchemas.Any(repositoryDescriptor.StartsWith))
            {
                if (!allowRemote)
                {
                    throw new InvalidUsageException($"{descriptorIsFor} must be local repository"
                                                    + mustLocalTailingMessage + ".");
                }
                var tempDir = Path.GetTempFileName();
                File.Delete(tempDir);
                Directory.CreateDirectory(tempDir);
                var options = new CloneOptions
                {
                    RecurseSubmodules = false
                };
                repositoryPath = Repository.Init(repositoryDescriptor);
                Directory.CreateDirectory(repositoryPath);

                repositoryPath = CommandGit.ShallowClone(repositoryDescriptor, tempDir, maxDepth);

                using var repo = new Repository(repositoryPath);
                foreach (var branch in repo.Branches)
                {
                    if (branch.IsRemote && branch.RemoteName == "origin")
                    {
                        var localName = branch.FriendlyName.RemovePrefix("origin/");
                        repo.Config.Set($"branch.{localName}.remote", "origin");
                        repo.Config.Set($"branch.{localName}.merge", $"refs/heads/{localName}");
                        repo.Branches.Add(localName, branch.Tip);
                    }
                }
            }
            else
#endif
            {
                repositoryPath = Path.Join(repositoryDescriptor, ".git");
                if (!Directory.Exists(repositoryPath))
                {
                    if (!allowEmpty)
                    {
                        throw new InvalidUsageException($"{descriptorIsFor} is not exists."
                                                        + mustExistsTailingMessage);
                    }

                    repositoryPath = Repository.Init(repositoryDescriptor);
                }
            }

            return(new Repository(repositoryPath));
        }
Beispiel #27
0
        /// <summary>
        /// Clone any object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceObject">The object to clone</param>
        /// <param name="options">Specify the Clone options</param>
        /// <param name="ignoreProperties">A list of property names to ignore</param>
        /// <returns></returns>
        public static T Clone <T>(this T sourceObject, CloneOptions options, params Expression <Func <T, object> >[] ignoreProperties)
        {
            var cloneProvider = new CloneProvider <T>();

            return(cloneProvider.Clone(sourceObject, options, CloneConfiguration.DefaultMaxDepth, ignoreProperties));
        }
Beispiel #28
0
 public object Clone(CloneOptions options)
 {
     return(this);
 }
Beispiel #29
0
        /// <summary>
        /// Clone any object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sourceObject">The object to clone</param>
        /// <param name="options">Specify the Clone options</param>
        /// <param name="ignorePropertiesOrPaths">A list of property names or fully qualified paths to ignore</param>
        /// <returns></returns>
        public static T Clone <T>(this T sourceObject, CloneOptions options, params string[] ignorePropertiesOrPaths)
        {
            var cloneProvider = new CloneProvider <T>();

            return(cloneProvider.Clone(sourceObject, options, CloneConfiguration.DefaultMaxDepth, ignorePropertiesOrPaths));
        }
Beispiel #30
0
        private static void UpdateExistingPullRequest(
            GitHubAuth gitHubAuth, PullRequestOptions prOptions, string commitMessage, GitHubBranch upstreamBranch)
        {
            // PullRequestCreator ends up force-pushing updates to an existing PR which is not great when the logic
            // gets called on a schedule (see https://github.com/dotnet/dotnet-docker/issues/1114). To avoid this,
            // it needs the ability to only update files that have changed from the existing PR.  Because the
            // PullRequestCreator class doesn't rely on there being a locally cloned repo, it doesn't have an
            // efficient way to determine whether files have changed or not. Update-dependencies would have to
            // implement logic which pulls down each file individually from the API and compare it to what exists
            // in the local repo.  Since that's not an efficient process, this method works by cloning the PR's
            // branch to a temporary repo location, grabbing the whole repo where the original updates from
            // update-dependencies were made and copying it into the temp repo, and committing and pushing
            // those changes in the temp repo back to the PR's branch.

            string tempRepoPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));

            try
            {
                string       branchName   = prOptions.BranchNamingStrategy.Prefix(upstreamBranch.Name);
                CloneOptions cloneOptions = new CloneOptions
                {
                    BranchName = branchName
                };

                // Clone the PR's repo/branch to a temp location
                Repository.Clone($"https://github.com/{gitHubAuth.User}/{Options.GitHubProject}", tempRepoPath, cloneOptions);

                // Remove all existing directories and files from the temp repo
                ClearRepoContents(tempRepoPath);

                // Copy contents of local repo changes to temp repo
                DirectoryCopy(".", tempRepoPath);

                using Repository repo = new Repository(tempRepoPath);
                RepositoryStatus status = repo.RetrieveStatus(new StatusOptions());

                // If there are any changes from what exists in the PR
                if (status.IsDirty)
                {
                    Commands.Stage(repo, "*");

                    Signature signature = new Signature(Options.GitHubUser, Options.GitHubEmail, DateTimeOffset.Now);
                    repo.Commit(commitMessage, signature, signature);

                    Branch branch = repo.Branches[$"origin/{branchName}"];

                    PushOptions pushOptions = new PushOptions
                    {
                        CredentialsProvider = (url, user, credTypes) => new UsernamePasswordCredentials
                        {
                            Username = Options.GitHubPassword,
                            Password = string.Empty
                        }
                    };

                    Remote remote      = repo.Network.Remotes["origin"];
                    string pushRefSpec = $@"refs/heads/{branchName}";

                    repo.Network.Push(remote, pushRefSpec, pushOptions);
                }
            }
            finally
            {
                // Cleanup temp repo
                DeleteRepoDirectory(tempRepoPath);
            }
        }
Beispiel #31
0
        private static async Task WriteContributorsToRepo(string username, string password)
        {
            var nameOfThankyouBranch = "thankyou";
            var repoUrl                     = _parsedOptions.gitRepositoryUrl;
            var contributorsHeader          = _parsedOptions.acknowledgementSection;
            var fileHoldingContributorsInfo = _parsedOptions.fileInRepoForAcknowledgement;

            string tempPathGitFolder = CreateTempFolderForTheRepo();

            var gitCredentialsHandler = new CredentialsHandler(
                (url, usernameFromUrl, types) =>
                new UsernamePasswordCredentials()
            {
                Username = username,
                Password = password
            });

            var cloneOptions = new CloneOptions();

            cloneOptions.CredentialsProvider = gitCredentialsHandler;
            LibGit2Sharp.Repository.Clone(repoUrl, tempPathGitFolder, cloneOptions);

            using (var repo = new LibGit2Sharp.Repository(tempPathGitFolder))
            {
                var remote        = repo.Network.Remotes["origin"];
                var defaultBranch = repo.Branches.FirstOrDefault(b => b.IsCurrentRepositoryHead == true);
                var refSpecs      = remote.FetchRefSpecs.Select(x => x.Specification);

                var remoteThankYouBranch = repo.Branches.FirstOrDefault(b => b.FriendlyName == repo.Network.Remotes.FirstOrDefault()?.Name + "/" + nameOfThankyouBranch);

                if (remoteThankYouBranch != null)
                {
                    Commands.Checkout(repo, remoteThankYouBranch);
                }

                if (repo.Head.FriendlyName != nameOfThankyouBranch)
                {
                    var newThankyouBranch = repo.CreateBranch(nameOfThankyouBranch);
                    repo.Branches.Update(newThankyouBranch,
                                         b => b.UpstreamBranch = newThankyouBranch.CanonicalName,
                                         b => b.Remote         = repo.Network.Remotes.First().Name);
                    Commands.Checkout(repo, newThankyouBranch);
                }


                var pathToReadme = Path.Combine(tempPathGitFolder, fileHoldingContributorsInfo);

                // Change the file and save it
                var inputLines = await File.ReadAllLinesAsync(pathToReadme);

                var outputLines = MarkdownProcessor.AddContributorsToMarkdownFile(inputLines, _contributorsToday);
                await File.WriteAllLinesAsync(pathToReadme, outputLines);

                var status = repo.RetrieveStatus(fileHoldingContributorsInfo);
                if (status == FileStatus.ModifiedInWorkdir)
                {
                    // Commit the file to the repo, on a non-master branch
                    repo.Index.Add(fileHoldingContributorsInfo);
                    repo.Index.Write();

                    var gitAuthorName  = _parsedOptions.gitAuthorName;
                    var gitAuthorEmail = _parsedOptions.gitAuthorEmail;

                    // Create the committer's signature and commit
                    var author    = new LibGit2Sharp.Signature(gitAuthorName, gitAuthorEmail, DateTime.Now);
                    var committer = author;

                    // Commit to the repository
                    var commit = repo.Commit("A new list of awesome contributors", author, committer);

                    //Push the commit to origin
                    LibGit2Sharp.PushOptions options = new LibGit2Sharp.PushOptions();
                    options.CredentialsProvider = gitCredentialsHandler;
                    repo.Network.Push(repo.Head, options);

                    // Login to GitHub with Octokit
                    var githubClient = new GitHubClient(new ProductHeaderValue(username));
                    githubClient.Credentials = new Octokit.Credentials(password);

                    try
                    {
                        //  Create a PR on the repo for the branch "thank you"
                        await githubClient.PullRequest.Create(username, "thankyou", new NewPullRequest("Give credit for people on Twitch chat", nameOfThankyouBranch, defaultBranch.FriendlyName));
                    }
                    catch (Exception ex)
                    {
                        // It's alright, the PR is already there. No harm is done.
                    }
                }
            }
        }
Beispiel #32
0
 public IRepository CloneRepository(string sourceUrl, string workdirPath, CloneOptions options)
 {
     Repository.Clone(sourceUrl, workdirPath, options);
     return(new Repository(workdirPath));
 }