/// <summary>
        /// Inserts a <see cref="LibGit2Sharp.Commit" /> into the object database by applying a <see cref="TreeDefinition"/>.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="changes">The changes.</param>
        /// <param name="message">The message.</param>
        /// <param name="author">The author.</param>
        /// <param name="committer">The committer.</param>
        /// <param name="hooks">The hooks.</param>
        /// <param name="options">The options.</param>
        /// <param name="mergeParent">The parent commit for a merge.</param>
        /// <returns>The created <see cref="LibGit2Sharp.Commit" />.</returns>
        internal static Commit CommitChanges(this IRepository repository, MetadataTreeChanges changes, string message, Signature author, Signature committer, GitHooks hooks, CommitOptions options = null, Commit mergeParent = null)
        {
            TreeDefinition definition;

            if (changes.OldRepository?.CommitId != null)
            {
                if (repository.Head.Tip.Id != changes.OldRepository.CommitId)
                {
                    throw new NotSupportedException("Changes are not based on the HEAD commit.");
                }
                var startCommit = repository.Lookup <Commit>(changes.OldRepository.CommitId);
                definition = TreeDefinition.From(startCommit);
            }
            else if (repository.Info.IsHeadUnborn)
            {
                definition = new TreeDefinition();
            }
            else
            {
                throw new NotSupportedException("Changes are not based on the HEAD commit.");
            }

            if (!hooks.OnCommitStarted(changes, message))
            {
                return(null);
            }

            changes.UpdateTreeDefinition(repository, definition);

            var result = Commit(repository, definition, message, author, committer, options, mergeParent);

            hooks.OnCommitCompleted(changes, message, result.Id);

            return(result);
        }
Example #2
0
        /// <summary>
        ///   Adds or replaces a <see cref="TreeEntryDefinition"/> at the specified <paramref name="targetTreeEntryPath"/> location.
        /// </summary>
        /// <param name="targetTreeEntryPath">The path within this <see cref="TreeDefinition"/>.</param>
        /// <param name="treeEntryDefinition">The <see cref="TreeEntryDefinition"/> to be stored at the described location.</param>
        /// <returns>The current <see cref="TreeDefinition"/>.</returns>
        public virtual TreeDefinition Add(string targetTreeEntryPath, TreeEntryDefinition treeEntryDefinition)
        {
            Ensure.ArgumentNotNullOrEmptyString(targetTreeEntryPath, "targetTreeEntryPath");
            Ensure.ArgumentNotNull(treeEntryDefinition, "treeEntryDefinition");

            if (Path.IsPathRooted(targetTreeEntryPath))
            {
                throw new ArgumentException("The provided path is an absolute path.");
            }

            if (treeEntryDefinition is TransientTreeTreeEntryDefinition)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
                                                                  "The {0} references a target which hasn't been created in the {1} yet. " +
                                                                  "This situation can occur when the target is a whole new {2} being created, or when an existing {2} is being updated because some of its children were added/removed.",
                                                                  typeof(TreeEntryDefinition).Name, typeof(ObjectDatabase).Name, typeof(Tree).Name));
            }

            Tuple <string, string> segments = ExtractPosixLeadingSegment(targetTreeEntryPath);

            if (segments.Item2 != null)
            {
                TreeDefinition td = RetrieveOrBuildTreeDefinition(segments.Item1, true);
                td.Add(segments.Item2, treeEntryDefinition);
            }
            else
            {
                AddEntry(segments.Item1, treeEntryDefinition);
            }

            return(this);
        }
        /// <summary>
        /// Removes the <see cref="TreeEntryDefinition"/> located at each of the
        /// specified <paramref name="treeEntryPaths"/>.
        /// </summary>
        /// <param name="td">The <see cref="TreeDefinition"/>.</param>
        /// <param name="treeEntryPaths">The paths within this <see cref="TreeDefinition"/>.</param>
        /// <returns>The current <see cref="TreeDefinition"/>.</returns>
        public static TreeDefinition Remove(this TreeDefinition td, IEnumerable <string> treeEntryPaths)
        {
            Ensure.ArgumentNotNull(td, "td");
            Ensure.ArgumentNotNull(treeEntryPaths, "treeEntryPaths");

            foreach (var treeEntryPath in treeEntryPaths)
            {
                td.Remove(treeEntryPath);
            }

            return(td);
        }
Example #4
0
        /// <summary>
        /// Builds a <see cref="TreeDefinition"/> from an existing <see cref="Tree"/>.
        /// </summary>
        /// <param name="tree">The <see cref="Tree"/> to be processed.</param>
        /// <returns>A new <see cref="TreeDefinition"/> holding the meta data of the <paramref name="tree"/>.</returns>
        public static TreeDefinition From(Tree tree)
        {
            Ensure.ArgumentNotNull(tree, "tree");

            var td = new TreeDefinition();

            foreach (TreeEntry treeEntry in tree)
            {
                td.Add(treeEntry.Name, treeEntry);
            }

            return td;
        }
Example #5
0
        /// <summary>
        ///   Builds a <see cref = "TreeDefinition" /> from an existing <see cref = "Tree" />.
        /// </summary>
        /// <param name = "tree">The <see cref = "Tree" /> to be processed.</param>
        /// <returns>A new <see cref = "TreeDefinition" /> holding the meta data of the <paramref name = "tree" />.</returns>
        public static TreeDefinition From(Tree tree)
        {
            Ensure.ArgumentNotNull(tree, "tree");

            var td = new TreeDefinition();

            foreach (TreeEntry treeEntry in tree)
            {
                td.AddEntry(treeEntry.Name, TreeEntryDefinition.From(treeEntry));
            }

            return(td);
        }
Example #6
0
        private TreeDefinition RetrieveOrBuildTreeDefinition(string treeName, bool shouldOverWrite)
        {
            TreeDefinition td;

            if (unwrappedTrees.TryGetValue(treeName, out td))
            {
                return(td);
            }

            TreeEntryDefinition treeEntryDefinition;
            bool hasAnEntryBeenFound = entries.TryGetValue(treeName, out treeEntryDefinition);

            if (hasAnEntryBeenFound)
            {
                switch (treeEntryDefinition.TargetType)
                {
                case TreeEntryTargetType.Tree:
                    td = From(treeEntryDefinition.Target as Tree);
                    break;

                case TreeEntryTargetType.Blob:
                case TreeEntryTargetType.GitLink:
                    if (shouldOverWrite)
                    {
                        td = new TreeDefinition();
                        break;
                    }

                    return(null);

                default:
                    throw new NotImplementedException();
                }
            }
            else
            {
                if (!shouldOverWrite)
                {
                    return(null);
                }

                td = new TreeDefinition();
            }

            entries[treeName] = new TransientTreeTreeEntryDefinition();

            unwrappedTrees.Add(treeName, td);
            return(td);
        }
Example #7
0
        /// <summary>
        /// Inserts a <see cref="LibGit2Sharp.Commit" /> into the object database by applying a <see cref="TreeDefinition"/>.
        /// </summary>
        /// <param name="repository">The repository.</param>
        /// <param name="definition">The tree definition.</param>
        /// <param name="message">The message.</param>
        /// <param name="author">The author.</param>
        /// <param name="committer">The committer.</param>
        /// <param name="options">The options.</param>
        /// <param name="mergeParent">The parent commit for a merge.</param>
        /// <returns>The created <see cref="LibGit2Sharp.Commit" />.</returns>
        internal static Commit Commit(this IRepository repository, TreeDefinition definition, string message, Signature author, Signature committer, CommitOptions options = null, Commit mergeParent = null)
        {
            if (options == null)
            {
                options = new CommitOptions();
            }

            var parents    = RetrieveParentsOfTheCommitBeingCreated(repository, options.AmendPreviousCommit, mergeParent).ToList();
            var tree       = repository.ObjectDatabase.CreateTree(definition);
            var commit     = repository.ObjectDatabase.CreateCommit(author, committer, message, tree, parents, false);
            var logMessage = commit.BuildCommitLogMessage(options.AmendPreviousCommit, repository.Info.IsHeadUnborn, parents.Count > 1);

            UpdateHeadAndTerminalReference(repository, commit, logMessage);
            return(commit);
        }
Example #8
0
        /// <summary>
        ///   Retrieves the <see cref="TreeEntryDefinition"/> located the specified <paramref name="treeEntryPath"/> path.
        /// </summary>
        /// <param name="treeEntryPath">The path within this <see cref="TreeDefinition"/>.</param>
        /// <returns>The found <see cref="TreeEntryDefinition"/> if any; null otherwise.</returns>
        public virtual TreeEntryDefinition this[string treeEntryPath]
        {
            get
            {
                Ensure.ArgumentNotNullOrEmptyString(treeEntryPath, "treeEntryPath");

                Tuple <string, string> segments = ExtractPosixLeadingSegment(treeEntryPath);

                if (segments.Item2 != null)
                {
                    TreeDefinition td = RetrieveOrBuildTreeDefinition(segments.Item1, false);
                    return(td == null ? null : td[segments.Item2]);
                }

                TreeEntryDefinition treeEntryDefinition;
                return(!entries.TryGetValue(segments.Item1, out treeEntryDefinition) ? null : treeEntryDefinition);
            }
        }
Example #9
0
        internal static Commit CommitChanges(this IRepository repository, ObjectRepositoryChangeCollection changes, IObjectRepositorySerializer serializer, string message, Signature author, Signature committer, GitHooks hooks, CommitOptions options = null, Commit mergeParent = null)
        {
            TreeDefinition definition;
            Commit         startCommit;

            if (changes.OldRepository?.CommitId != null)
            {
                if (repository.Head.Tip.Id != changes.OldRepository.CommitId)
                {
                    throw new GitObjectDbException("Changes are not based on the HEAD commit.");
                }
                startCommit = repository.Lookup <Commit>(changes.OldRepository.CommitId);
                definition  = TreeDefinition.From(startCommit);
            }
            else if (repository.Info.IsHeadUnborn)
            {
                startCommit = null;
                definition  = new TreeDefinition();
            }
            else
            {
                throw new GitObjectDbException("Changes are not based on the HEAD commit.");
            }

            if (!hooks.OnCommitStarted(changes, message))
            {
                return(null);
            }

            repository.UpdateTreeDefinition(changes, definition, serializer, startCommit);

            var result = Commit(repository, definition, message, author, committer, options, mergeParent);

            hooks.OnCommitCompleted(changes, message, result.Id);

            return(result);
        }
Example #10
0
        public void NewPost(Post post)
        {
            using (var repo = new Repository(_directory.FullName))
            {
                var json = JsonConvert.SerializeObject(post);
                var sig = new Signature(post.Author.Name, post.Author.Identifier, post.Timestamp);

                // Create post structure
                var votesDir = repo.ObjectDatabase.CreateTree(new TreeDefinition());
                var repliesDir = repo.ObjectDatabase.CreateTree(new TreeDefinition());
                var postRoot = new TreeDefinition();
                postRoot.Add(VOTES_DIR, votesDir);
                postRoot.Add(REPLIES_DIR, repliesDir);

                var commit = CommitToBranch(repo, CONTENT_BRANCH, json, sig, repo.ObjectDatabase.CreateTree(postRoot));
                // Create a named branch for all future content on this post
                repo.CreateBranch(commit.Sha, commit);
            }
        }
Example #11
0
        /// <summary>
        ///   Inserts a <see cref = "Tree"/> into the object database, created from a <see cref = "TreeDefinition"/>.
        /// </summary>
        /// <param name = "treeDefinition">The <see cref = "TreeDefinition"/>.</param>
        /// <returns>The created <see cref = "Tree"/>.</returns>
        public virtual Tree CreateTree(TreeDefinition treeDefinition)
        {
            Ensure.ArgumentNotNull(treeDefinition, "treeDefinition");

            return treeDefinition.Build(repo);
        }
Example #12
0
        public void Vote(Post post, Identity voter, VoteType vote)
        {
            using (var repo = new Repository(_directory.FullName))
            {
                var postCommit = repo.Branches[post.Id].Tip;

                // Retrieve existing tree
                var commitRoot = postCommit.Tree;
                var votesDir = (Tree)commitRoot[VOTES_DIR].Target;
                var repliesDir = (Tree)commitRoot[REPLIES_DIR].Target;

                // Copy existing content to new votes treedef
                var newVotesDir = new TreeDefinition();
                foreach (TreeEntry obj in votesDir)
                {
                    newVotesDir.Add(obj.Name, obj);
                }
                // Add new vote to new votes treedef
                Vote(repo, newVotesDir, vote);

                // Assemble new root treedef
                var newPostRoot = new TreeDefinition();
                newPostRoot.Add(VOTES_DIR, repo.ObjectDatabase.CreateTree(newVotesDir));
                newPostRoot.Add(REPLIES_DIR, repliesDir);

                // Commit new root treedef to post branch
                var message = string.Format("{0} by {1}", vote, voter.Name);
                var sig = new Signature(voter.Name, voter.Identifier, DateTimeOffset.UtcNow);
                CommitToBranch(repo, post.Id, message, sig, repo.ObjectDatabase.CreateTree(newPostRoot));
            }
        }
Example #13
0
 /// <summary>
 ///   Inserts a <see cref = "Tree"/> into the object database, created from a <see cref = "TreeDefinition"/>.
 /// </summary>
 /// <param name = "treeDefinition">The <see cref = "TreeDefinition"/>.</param>
 /// <returns>The created <see cref = "Tree"/>.</returns>
 public Tree CreateTree(TreeDefinition treeDefinition)
 {
     return(treeDefinition.Build(repo));
 }
Example #14
0
            public void Prepare()
            {
                parent = repository.Head.Tip;
                if (parent == null)
                {
                    treeDefinition = new TreeDefinition();
                }
                else
                {
                    treeDefinition = TreeDefinition.From(parent.Tree);
                }

                GitReset();
            }
Example #15
0
 private void Vote(Repository repo, TreeDefinition votesDir, VoteType vote)
 {
     switch (vote)
     {
         case LibBastion.VoteType.Upvote:
             votesDir.Add(UPVOTE, Upvote(repo), Mode.NonExecutableFile);
             break;
         case LibBastion.VoteType.Downvote:
             votesDir.Add(DOWNVOTE, Downvote(repo), Mode.NonExecutableFile);
             break;
     }
 }
Example #16
0
        private static void UpdateChangeTreeDefinitions(IRepository repository, IEnumerable <ObjectRepositoryEntryChanges> changes, TreeDefinition definition, IObjectRepositorySerializer serializer)
        {
            var buffer = new StringBuilder();

            foreach (var change in changes)
            {
                if (change.New is IObjectRepositoryIndex index)
                {
                    // Index are managed separately
                    continue;
                }
                buffer.Clear();
                var nested = serializer.Serialize(change.New, buffer);
                definition.Add(change.Path, repository.CreateBlob(buffer), Mode.NonExecutableFile);
                foreach (var info in nested)
                {
                    var nestedPath = change.New.GetDataPath(info.FileName);
                    definition.Add(nestedPath, repository.CreateBlob(info.Data), Mode.NonExecutableFile);
                }
            }
        }
Example #17
0
 public GitTreeBuilder(ObjectDatabase objectDatabase, Tree tree)
 {
     _treeDefinition = TreeDefinition.From(tree);
     _objectDatabase = objectDatabase;
 }
Example #18
0
        private static void UpdateDeletionTreeDefinitions(IEnumerable <ObjectRepositoryEntryChanges> deletions, TreeDefinition definition, Commit oldCommit = null)
        {
            foreach (var deleted in deletions)
            {
                if (oldCommit == null)
                {
                    throw new GitObjectDbException("Unexpected state: no deletion should be detected on blank commit.");
                }

                var folderEntry = oldCommit[deleted.Path.GetParentPath()];
                if (folderEntry != null)
                {
                    definition.Remove(folderEntry.Path);
                }
            }
        }
Example #19
0
        private static void UpdateIndexTreeDefinitions(IRepository repository, ObjectRepositoryChangeCollection changes, TreeDefinition definition, IObjectRepositorySerializer serializer)
        {
            var buffer = new StringBuilder();

            foreach (var index in changes.NewRepository.Indexes)
            {
                var fullScan = changes.Added.Any(c => c.New.Id == index.Id);
                if (UpdateAndSerializerIndex(index, changes, serializer, buffer, fullScan))
                {
                    definition.Add(index.GetDataPath(), repository.CreateBlob(buffer), Mode.NonExecutableFile);
                }
            }
        }
Example #20
0
 public GitTreeBuilder(ObjectDatabase objectDatabase)
 {
     _treeDefinition = new TreeDefinition();
     _objectDatabase = objectDatabase;
 }
Example #21
0
        internal static void UpdateTreeDefinition(this IRepository repository, ObjectRepositoryChangeCollection changes, TreeDefinition definition, IObjectRepositorySerializer serializer, Commit oldCommit = null)
        {
            if (repository == null)
            {
                throw new ArgumentNullException(nameof(repository));
            }
            if (definition == null)
            {
                throw new ArgumentNullException(nameof(definition));
            }

            UpdateChangeTreeDefinitions(repository, changes.Modified, definition, serializer);
            UpdateChangeTreeDefinitions(repository, changes.Added, definition, serializer);
            UpdateDeletionTreeDefinitions(changes.Deleted, definition, oldCommit);
            UpdateIndexTreeDefinitions(repository, changes, definition, serializer);
        }
Example #22
0
        private TreeDefinition RetrieveOrBuildTreeDefinition(string treeName, bool shouldOverWrite)
        {
            TreeDefinition td;

            if (unwrappedTrees.TryGetValue(treeName, out td))
            {
                return td;
            }

            TreeEntryDefinition treeEntryDefinition;
            bool hasAnEntryBeenFound = entries.TryGetValue(treeName, out treeEntryDefinition);

            if (hasAnEntryBeenFound)
            {
                switch (treeEntryDefinition.TargetType)
                {
                    case TreeEntryTargetType.Tree:
                        td = From(treeEntryDefinition.Target as Tree);
                        break;

                    case TreeEntryTargetType.Blob:
                    case TreeEntryTargetType.GitLink:
                        if (shouldOverWrite)
                        {
                            td = new TreeDefinition();
                            break;
                        }

                        return null;

                    default:
                        throw new NotImplementedException();
                }
            }
            else
            {
                if (!shouldOverWrite)
                {
                    return null;
                }

                td = new TreeDefinition();
            }

            entries[treeName] = new TransientTreeTreeEntryDefinition();

            unwrappedTrees.Add(treeName, td);
            return td;
        }
        /// <summary>
        /// Write a config back to the global git repository.
        /// </summary>
        /// <param name="config"></param>
        public void WriteConfig(Config config)
        {
            using (var repository = new Repository(LocalGitRepositoryLocation))
            {
                var remote = repository.Network.Remotes[ConfigurationRemote];
                repository.Network.Fetch(remote);

                // Create a blob from the content stream
                Blob blob;
                var serializedObject = new JavaScriptSerializer().Serialize(config);
                var contentBytes = Encoding.UTF8.GetBytes(serializedObject);
                using (var memoryStream = new MemoryStream(contentBytes)) { blob = repository.ObjectDatabase.CreateBlob(memoryStream); }

                // Put the blob in a tree
                var treeDefinition = new TreeDefinition();
                treeDefinition.Add(GitConfigurationFile, blob, Mode.NonExecutableFile);
                var tree = repository.ObjectDatabase.CreateTree(treeDefinition);

                // Committer and author
                var committer = new Signature(string.Format("{0}@{1}", Environment.UserName, Environment.MachineName), TeamEmailAddress, DateTime.Now);
                var author = committer;

                //Create the commit
                var refOriginMaster = repository.Refs[ConfigurationRemoteRef];
                var parentCommit = refOriginMaster != null ? new[]{repository.Lookup<Commit>(refOriginMaster.TargetIdentifier)} : new Commit[0];
                var commit = repository.ObjectDatabase.CreateCommit(author, committer, "Updating config.json", tree, parentCommit, false);

                // Update the HEAD reference to point to the latest commit
                repository.Refs.UpdateTarget(repository.Refs.Head, commit.Id);

                repository.Network.Push(remote, repository.Refs.Head.CanonicalName, ConfigurationRef);
            }
        }
Example #24
0
        /// <summary>
        /// Inserts a <see cref="Tree"/> into the object database, created from a <see cref="TreeDefinition"/>.
        /// </summary>
        /// <param name="treeDefinition">The <see cref="TreeDefinition"/>.</param>
        /// <returns>The created <see cref="Tree"/>.</returns>
        public virtual Tree CreateTree(TreeDefinition treeDefinition)
        {
            Ensure.ArgumentNotNull(treeDefinition, "treeDefinition");

            return(treeDefinition.Build(repo));
        }
Example #25
0
 /// <summary>
 ///   Inserts a <see cref = "Tree"/> into the object database, created from a <see cref = "TreeDefinition"/>.
 /// </summary>
 /// <param name = "treeDefinition">The <see cref = "TreeDefinition"/>.</param>
 /// <returns>The created <see cref = "Tree"/>.</returns>
 public Tree CreateTree(TreeDefinition treeDefinition)
 {
     return treeDefinition.Build(repo);
 }