public static GitBlobWriter AsWriter(this GitBlob blob) { if (blob is null) { throw new ArgumentNullException(nameof(blob)); } var bw = GitBlobWriter.CreateFrom(blob.GetBucket()); bw.PutId(blob.Id); // TODO: Cleanup return(bw); }
/// <summary> /// Imports git objects from the 'fast-import' source <paramref name="source"/> /// </summary> /// <param name="repository"></param> /// <param name="source"></param> /// <returns></returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="BucketException"></exception> /// <remarks>Imports objects and updates references based on information in <paramref name="source"/></remarks> public static async ValueTask FastImportAsync(this GitRepository repository, Bucket source) { if (repository is null) { throw new ArgumentNullException(nameof(repository)); } else if (source is null) { throw new ArgumentNullException(nameof(source)); } using (source) { var marks = new Dictionary <string, GitId>(); var refs = new Dictionary <string, GitId>(); while (true) { BucketBytes bb; BucketEol eol; string type; string follow; while (true) { (bb, eol) = await source.ReadUntilEolFullAsync(BucketEol.LF).ConfigureAwait(false); if (bb.IsEof) { return; } var parts = bb.Split((byte)' ', 2); if (parts.Length == 2) { type = parts[0].ToASCIIString(); follow = parts[1].ToUTF8String(eol); } else { type = bb.ToUTF8String(eol); follow = ""; } if (type.Length == 0) { break; } if (type == "reset") { continue; } else if (type == "from") { (bb, eol) = await source.ReadUntilEolAsync(BucketEol.LF).ConfigureAwait(false); continue; } else { break; } } if (type.Length == 0) { break; } string?mark; if (type != "tag") { (bb, eol) = await source.ReadUntilEolAsync(BucketEol.LF).ConfigureAwait(false); if (!bb.StartsWithASCII("mark ")) { throw new BucketException($"Missing mark: {bb.ToUTF8String()}"); } mark = bb.Slice(5).ToASCIIString(eol); } else { mark = null; } List <string>?headers = new List <string>(); while (true) { (bb, eol) = await source.ReadUntilEolAsync(BucketEol.LF).ConfigureAwait(false); if (bb.StartsWithASCII("data ")) { break; } else { var n = bb.IndexOf((byte)' '); if (n < 0) { throw new BucketException($"Bad header {bb.ToUTF8String(eol)}"); } headers.Add(bb.ToUTF8String(eol)); } } long len = Convert.ToInt64(bb.Slice(5).ToASCIIString(eol), 10); { Bucket body = source.TakeExact(len).NoClose(); GitId? id = null; switch (type) { case "blob": { GitBlobWriter bw = GitBlobWriter.CreateFrom(body); id = await bw.WriteToAsync(repository).ConfigureAwait(false); (bb, eol) = await source.ReadUntilEolFullAsync(BucketEol.LF).ConfigureAwait(false); if (bb.IsEof) { return; } break; } case "commit": using (body) { string message = (await body.ReadFullAsync((int)len).ConfigureAwait(false)).ToUTF8String(); var cw = await FillCommit(message, source, marks, repository).ConfigureAwait(false); string author = headers.Single(x => x.StartsWith("author ", StringComparison.Ordinal)).Substring(7); string committer = headers.Single(x => x.StartsWith("committer ", StringComparison.Ordinal)).Substring(10); cw.Message = message; if (Buckets.Git.GitSignatureRecord.TryReadFromBucket(Encoding.UTF8.GetBytes(author), out var authSig)) { cw.Author = new GitSignature(authSig); } if (Buckets.Git.GitSignatureRecord.TryReadFromBucket(Encoding.UTF8.GetBytes(committer), out var commitSig)) { cw.Committer = new GitSignature(commitSig); } id = await cw.WriteToAsync(repository).ConfigureAwait(false); if (!string.IsNullOrEmpty(follow) && id is not null) { refs[follow] = id; } break; } case "tag": using (body) { string message = (await body.ReadFullAsync((int)len).ConfigureAwait(false)).ToUTF8String(); string from = headers.Single(x => x.StartsWith("from ", StringComparison.Ordinal)).Substring(5); string tagger = headers.Single(x => x.StartsWith("tagger ", StringComparison.Ordinal)).Substring(7); var c = repository.Commits[marks[from]] ?? throw new GitRepositoryException("Failed to load commit"); GitTagObjectWriter tw = GitTagObjectWriter.Create(c, follow); tw.Message = message; if (Buckets.Git.GitSignatureRecord.TryReadFromBucket(Encoding.UTF8.GetBytes(tagger), out var tagSig)) { tw.Tagger = new GitSignature(tagSig); } id = await tw.WriteToAsync(repository).ConfigureAwait(false); refs[$"refs/tags/{follow}"] = id; break; } default: body.Dispose(); throw new BucketException($"Unexpected object type {type}"); } await body.ReadSkipAsync(long.MaxValue).ConfigureAwait(false); if (mark is not null && id is not null) { marks.Add(mark, id); } } } if (refs.Count > 0) { using (var t = repository.References.CreateUpdateTransaction()) { foreach (var k in refs) { t.Update(k.Key, k.Value); } await t.CommitAsync().ConfigureAwait(false); } } } }