2 using System
.Collections
.Generic
;
9 Branch m_CurrentBranch
= null;
10 public Branch CurrentBranch { get { return m_CurrentBranch; }
}
12 List
<Branch
> m_branches
= new List
<Branch
>();
13 public List
<Branch
> Branches { get { return new List<Branch>(m_branches); }
}
15 Tree m_workingSet
= null;
16 public Tree WorkingSet { get { return m_workingSet; }
}
18 List
<Remote
> m_remotes
= new List
<Remote
>();
19 public List
<Remote
> Remotes { get { return new List<Remote>(m_remotes); }
}
21 List
<Tag
> m_tags
= new List
<Tag
>();
22 public List
<Tag
> Tags { get { return new List<Tag>(m_tags); }
}
25 public string Path { get { return m_path; }
}
27 public static string DirectorySeparator { get { return "/"; }
} //git-ls always uses "/"
29 protected static bool m_mono
= Type
.GetType ("Mono.Runtime") != null;
30 public static bool Mono { get { return m_mono; }
}
32 protected static string[] m_lineSep
= { System.Environment.NewLine }
;
33 public static string[] LineSeparator { get { return m_lineSep; }
}
35 public Repo(string path
)
44 protected bool ValidateRepo()
46 return ValidateRepo(m_path
);
49 public static bool ValidateRepo(string path
)
51 Executioner e
= Executioner
.GetExecutioner(path
, false);
53 return 0 == e
.Execute("git-rev-parse", "--git-dir");
62 Executioner e
= Executioner
.GetExecutioner(m_path
);
63 return 0 == e
.Execute("git-init-db");
66 public bool Commit(string message
, string[] signedOff
, out Commit commited
)
68 throw new NotImplementedException();
71 public bool GetFiles(List
<string> paths
, out List
<File
> files
)
75 files
= new List
<Git
.File
>();
79 paths
[0] = "\"" + paths
[0];
80 paths
[paths
.Count
- 1] = paths
[paths
.Count
- 1] + "\"";
81 string pathset
= String
.Join("\" \"", paths
.ToArray());
82 string input
= "-c -d -m -o -t -z -k " + pathset
;
84 Dictionary
<string, File
> filesMap
= new Dictionary
<string, File
>();
85 Executioner e
= Executioner
.GetExecutioner(m_path
);
86 if (0 == e
.Execute("git-ls-files", input
, "", out output
, out error
))
88 ParseLSOutput(output
, filesMap
);
89 UpdateFromIndex(filesMap
, pathset
);
90 files
= new List
<Git
.File
>(filesMap
.Values
);
97 public bool Add(List
<string> paths
, out List
<File
> files
)
99 Executioner e
= Executioner
.GetExecutioner(m_path
);
101 string input
= String
.Join("\n", paths
.ToArray());
102 string output
, error
;
103 if (e
.Execute("git-update-index", "--add --stdin", input
, out output
, out error
) == 0)
105 return GetFiles(paths
, out files
);
110 protected string GetPathsList(List
<string> paths
)
112 List
<string> pathsCopy
= new List
<string>(paths
);
113 pathsCopy
[0] = " \"" + pathsCopy
[0];
114 pathsCopy
[paths
.Count
- 1] = pathsCopy
[paths
.Count
- 1] + "\"";
115 return String
.Join("\" \"", pathsCopy
.ToArray());
118 public bool Revert(List
<string> paths
, out List
<File
> files
)
122 files
= new List
<File
>();
125 Executioner e
= Executioner
.GetExecutioner(m_path
);
127 string input
= String
.Join("\n", paths
.ToArray());
128 string output
, error
;
130 if (e
.Execute("git-update-index", "--add --remove --stdin", input
, out output
, out error
) == 0 &&
131 e
.Execute("git-update-index", "--refresh") == 0)
133 return GetFiles(paths
, out files
);
139 public bool Remove(List
<string> paths
, out List
<File
> files
)
143 files
= new List
<File
>();
146 Executioner e
= Executioner
.GetExecutioner(m_path
);
148 string input
= GetPathsList(paths
);
149 if (e
.Execute("git-rm", "--cached -f " + input
) == 0)
151 return GetFiles(paths
, out files
);
157 public bool Checkout(Treeish t
)
163 Executioner e
= Executioner
.GetExecutioner(m_path
);
164 return 0 == e
.Execute("git-checkout", t
.ID
);
167 public bool Checkout(Tag t
, string newBranchName
)
173 Executioner e
= Executioner
.GetExecutioner(m_path
);
174 if (0 == e
.Execute("git-checkout", "-b " + newBranchName
+ " " + t
.Name
))
182 protected bool UpdateBranches()
184 Executioner e
= Executioner
.GetExecutioner(m_path
, false);
185 string output
, error
;
186 if (0 == e
.Execute("git-branch", "", "", out output
, out error
))
189 foreach (string s
in output
.Split(m_lineSep
, StringSplitOptions
.RemoveEmptyEntries
))
191 string branchName
= s
.Trim();
192 if (branchName
.StartsWith("*"))
194 branchName
= branchName
.Substring(2);
195 branchName
= branchName
.Trim();
196 m_CurrentBranch
= new Branch(m_path
, branchName
);
197 m_branches
.Add(m_CurrentBranch
);
201 m_branches
.Add(new Branch(m_path
, branchName
));
209 protected bool UpdateTags()
211 Executioner e
= Executioner
.GetExecutioner(m_path
, false);
212 string output
= null, error
= null;
213 if (0 == e
.Execute("git-rev-parse", "--symbolic --tags", "", out output
, out error
))
216 foreach (string s
in output
.Split(m_lineSep
, StringSplitOptions
.RemoveEmptyEntries
))
218 m_tags
.Add(new Tag(s
.Trim(), m_path
));
225 public bool NewBranch(string name
, Branch startPoint
, Remote remote
, bool bForce
)
227 Executioner e
= Executioner
.GetExecutioner(m_path
);
228 string arguments
= name
;
231 arguments
= arguments
+ " -f";
233 if (null != startPoint
)
235 arguments
= arguments
+ " " + startPoint
.Name
;
239 arguments
= arguments
+ " --track " + remote
.Name
;
241 bool retval
= 0 == e
.Execute("git-branch", arguments
);
246 public bool RenameBranch(Branch b
, string newName
, bool bForce
)
248 Executioner e
= Executioner
.GetExecutioner(m_path
);
249 bool retval
= 0 == e
.Execute("git-branch", bForce
? "-M " : "-m " + b
.Name
+ " " + newName
);
254 public bool DeleteBranch(Branch b
, bool bForce
)
256 Executioner e
= Executioner
.GetExecutioner(m_path
);
257 bool retval
= 0 == e
.Execute("git-branch", bForce
? "-D " : "-d " + b
.Name
);
262 public List
<File
> ListFiles()
264 Executioner e
= Executioner
.GetExecutioner(m_path
, true);
265 string output
, error
;
266 Dictionary
<string, File
> files
= new Dictionary
<string, File
>();
267 if (0 == e
.Execute("git-ls-files", "-c -d -m -o -k -t -z", "", out output
, out error
))
269 ParseLSOutput(output
, files
);
271 UpdateFromIndex(files
, "");
272 return new List
<File
>(files
.Values
);
275 private void UpdateFromIndex(Dictionary
<string, File
> filesMap
, string paths
)
277 Executioner e
= Executioner
.GetExecutioner(m_path
, true);
278 string output
, error
;
279 if (0 == e
.Execute("git-diff-index", "-B -M -C -z --name-status HEAD " + paths
, "", out output
, out error
))
281 string[] lines
= output
.Split("\0".ToCharArray());
282 for (int i
= 0; i
< lines
.Length
- 1; i
+= 2)
284 string front
= lines
[i
][0].ToString();
285 string file
= lines
[i
+ 1].Trim();
286 if (file
.StartsWith("\""))
288 file
= file
.Substring(1);
290 if (file
.EndsWith("\""))
292 file
= file
.Substring(0, file
.Length
- 1);
295 if (filesMap
.TryGetValue(file
, out f
))
303 private void ParseLSOutput(string output
, Dictionary
<string, File
> files
)
305 string[] lines
= output
.Split("\0".ToCharArray());
306 System
.Console
.WriteLine("path: " + m_path
+ " files: " + lines
.Length
);
307 foreach (string oneline
in lines
)
309 string line
= oneline
.Trim();
315 string front
= line
[0].ToString();
316 line
= line
.Substring(2);
317 if (line
.StartsWith("\""))
319 line
= line
.Substring(1);
321 if (line
.EndsWith("\""))
323 line
= line
.Substring(0, line
.Length
- 1);
326 if (!files
.TryGetValue(line
, out f
))//work around git reporting files twice sometimes
328 f
= new File(null, line
);
333 f
.State
= FileState
.Unknown
;
337 f
.State
= FileState
.Normal
;
342 public bool Reset(string commit
)
344 Executioner e
= Executioner
.GetExecutioner(m_path
);
345 string id
= null == commit
? "HEAD" : commit
;
346 return (0 == e
.Execute("git-read-tree", "--reset -u " + id
));
349 public bool GetLog(Commit start
, int count
, out List
<Commit
> commits
)
351 Executioner e
= Executioner
.GetExecutioner(m_path
, true);
352 string args
= "-n " + count
+ Git
.Commit
.FormatString
;
357 string output
, error
;
358 if (0 == e
.Execute("git-log", args
, "", out output
, out error
))
360 string[] records
= output
.Split(Repo
.LineSeparator
, StringSplitOptions
.RemoveEmptyEntries
);
361 commits
= new List
<Commit
>();
362 foreach (string record
in records
)
364 Commit c
= Git
.Commit
.GetCommit(m_path
, record
);