private async Task<Errorable<Commit>> persistCommit(Commit cm)
        {
            FileInfo tmpFile = system.getTemporaryFile();

            // Write the commit contents to the file:
            using (var fs = new FileStream(tmpFile.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 16834, useAsync: true))
            {
                await fs.WriteRawAsync(cm.WriteTo(new StringBuilder()).ToString());
            }

            lock (FileSystem.SystemLock)
            {
                FileInfo fi = system.getPathByID(cm.ID);

                // NOTE: if the record already exists we can either error out or overwrite the existing file with contents known to be good in the case the existing file got corrupt.
                // Let's stick with the self-repair scenario since erroring out doesn't help anyone.
                if (fi.Exists)
                {
                    Debug.WriteLine(String.Format("Self-repair scenario: overwriting old CommitID {0} with new contents", cm.ID));
                    fi.Delete();
                }

                // Create directory if it doesn't exist:
                if (!fi.Directory.Exists)
                {
                    Debug.WriteLine(String.Format("New DIR '{0}'", fi.Directory.FullName));
                    fi.Directory.Create();
                }

                Debug.WriteLine(String.Format("New COMMIT '{0}'", fi.FullName));
                File.Move(tmpFile.FullName, fi.FullName);
            }

            return cm;
        }
 public Builder(Commit imm)
 {
     this.Parents = (imm.Parents).ToList((imm.Parents).Length);
     this.TreeID = imm.TreeID;
     this.Committer = imm.Committer;
     this.DateCommitted = imm.DateCommitted;
     this.Message = imm.Message;
 }
 public Task<Errorable<Commit>> PersistCommit(Commit cm)
 {
     return db.ExecuteNonQueryAsync(new PersistCommit(cm));
 }
        private async Task<Errorable<Commit[]>> getCommitsRecursively(CommitID id, int depthLevel, int depthMaximum)
        {
            // Get the current commit:
            var eroot = await getCommit(id).ConfigureAwait(continueOnCapturedContext: false);
            if (eroot.HasErrors) return eroot.Errors;

            var root = eroot.Value;
            var rootArr = new Commit[1] { root };

            // We have no parents:
            if (root.Parents.Length == 0)
                return rootArr;

            // This is the last depth level:
            if (depthLevel >= depthMaximum)
                return rootArr;

            // Recurse up the commit parents:
            Task<Errorable<Commit[]>>[] tasks = new Task<Errorable<Commit[]>>[root.Parents.Length];
            for (int i = 0; i < root.Parents.Length; ++i)
            {
                tasks[i] = getCommitsRecursively(root.Parents[i], depthLevel + 1, depthMaximum);
            }

            // Await all the tree retrievals:
            var allCommits = await Task.WhenAll(tasks).ConfigureAwait(continueOnCapturedContext: false);

            // Roll up all the errors:
            ErrorContainer errors =
                (
                    from ecms in allCommits
                    where ecms.HasErrors
                    select ecms.Errors
                ).Aggregate(new ErrorContainer(), (acc, err) => acc + err);

            if (errors.HasAny) return errors;

            // Flatten out the tree arrays:
            var flattened =
                from ecms in allCommits
                from cm in ecms.Value
                select cm;

            // Return the final array:
            return rootArr.Concat(flattened).ToArray(allCommits.Sum(ca => ca.Value.Length) + 1);
        }
        public async Task<Errorable<Commit>> PersistCommit(Commit cm)
        {
            await Task.Run(() => persistCommit(cm)).ConfigureAwait(continueOnCapturedContext: false);

            return cm;
        }