1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using LibGit2Sharp.Wrapper;
namespace LibGit2Sharp
{
public class ObjectBuilder : IBuilder
{
private readonly IDictionary<ObjectType, Func<IntPtr, GitObject>> _builderMapper;
public ObjectBuilder()
{
_builderMapper = InitMapper();
}
private IDictionary<ObjectType, Func<IntPtr, GitObject>> InitMapper()
{
var map = new Dictionary<ObjectType, Func<IntPtr, GitObject>>();
map.Add(ObjectType.Commit, BuildCommit);
map.Add(ObjectType.Tag, BuildTag);
map.Add(ObjectType.Tree, BuildTree);
map.Add(ObjectType.Blob, BuildBlob);
return map;
}
private GitObject BuildTag(IntPtr gitObjectPtr)
{
var gitTag = (git_tag)Marshal.PtrToStructure(gitObjectPtr, typeof(git_tag));
Signature tagTagger = BuildSignature(gitTag.tagger);
GitObject tagTarget = BuildFrom(gitTag.target, (ObjectType)gitTag.type);
return new Tag(ObjectId.ToString(gitTag.tag.id.id), gitTag.tag_name, tagTarget, tagTagger, gitTag.message);
}
private static GitObject BuildCommit(IntPtr gitObjectPtr)
{
var gitCommit = (git_commit)Marshal.PtrToStructure(gitObjectPtr, typeof(git_commit));
Signature commitAuthor = BuildSignature(gitCommit.author);
Signature commitCommitter = BuildSignature(gitCommit.committer);
var commitTree = (Tree)BuildTree(gitCommit.tree);
var numberOfParents = (int)gitCommit.parents.length;
IList<GitObject> parents = new List<GitObject>(numberOfParents);
for (int i = 0; i < numberOfParents; i++)
{
IntPtr nextParentPtrPtr = IntPtr.Add(gitCommit.parents.contents, i * Marshal.SizeOf(typeof(IntPtr)));
IntPtr parentPtr = Marshal.ReadIntPtr(nextParentPtrPtr);
var parentGitObject = BuildGitObject(parentPtr);
parents.Add(parentGitObject);
}
return new Commit(ObjectId.ToString(gitCommit.commit.id.id), commitAuthor, commitCommitter, gitCommit.message, gitCommit.message_short, commitTree, parents);
}
private static GitObject BuildTree(IntPtr gitObjectPtr)
{
var gitTree = (git_tree)Marshal.PtrToStructure(gitObjectPtr, typeof(git_tree));
return new Tree(ObjectId.ToString(gitTree.tree.id.id));
}
private static GitObject BuildBlob(IntPtr gitObjectPtr)
{
throw new NotImplementedException();
//var gitBlob = (git_blob)Marshal.PtrToStructure(gitObjectPtr, typeof(git_blob));
//return new Blob(...)
}
private static Signature BuildSignature(IntPtr gitObjectPtr)
{
if (gitObjectPtr == IntPtr.Zero)
{
return null; // TODO: Fix full parsing of commits.
}
var gitPerson = (git_signature)Marshal.PtrToStructure(gitObjectPtr, typeof(git_signature));
return new Signature(gitPerson.name, gitPerson.email, new GitDate((int)gitPerson.time, gitPerson.offset));
}
private static GitObject BuildGitObject(IntPtr gitObjectPtr)
{
var gitObject = (git_object)Marshal.PtrToStructure(gitObjectPtr, typeof(git_object));
return new GitObject(ObjectId.ToString(gitObject.id.id), (ObjectType)gitObject.source.raw.type);
}
public GitObject BuildFrom(IntPtr gitObjectPtr, ObjectType type)
{
if (gitObjectPtr == IntPtr.Zero)
{
throw new ArgumentNullException("gitObjectPtr");
}
if (!_builderMapper.Keys.Contains(type))
{
return BuildGitObject(gitObjectPtr);
}
return _builderMapper[type](gitObjectPtr);
}
}
}
|