Basic Commit viewer.
[Gitrdone.git] / Git / Repo.cs
blob54125566dc425e6d1275fa0fe401712187156a2b
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
5 namespace Git
7 public class Repo
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); } }
24 string m_path;
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)
37 m_path = path;
38 if (UpdateBranches())
40 UpdateTags();
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");
56 public bool Init()
58 if (ValidateRepo())
60 return true;
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)
73 if (paths.Count < 1)
75 files = new List<Git.File>();
76 return true;
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;
83 string output, error;
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);
91 return true;
93 files = null;
94 return false;
97 public bool Add(List<string> paths, out List<File> files)
99 Executioner e = Executioner.GetExecutioner(m_path);
100 files = null;
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);
107 return false;
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)
120 if (paths.Count < 1)
122 files = new List<File>();
123 return true;
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);
135 files = null;
136 return false;
139 public bool Remove(List<string> paths, out List<File> files)
141 if (paths.Count < 1)
143 files = new List<File>();
144 return true;
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);
153 files = null;
154 return false;
157 public bool Checkout(Treeish t)
159 if (!t.Verify())
161 return false;
163 Executioner e = Executioner.GetExecutioner(m_path);
164 return 0 == e.Execute("git-checkout", t.ID);
167 public bool Checkout(Tag t, string newBranchName)
169 if (!t.Verify())
171 return false;
173 Executioner e = Executioner.GetExecutioner(m_path);
174 if (0 == e.Execute("git-checkout", "-b " + newBranchName + " " + t.Name))
176 UpdateBranches();
177 return true;
179 return false;
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))
188 m_branches.Clear();
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);
199 else
201 m_branches.Add(new Branch(m_path, branchName));
204 return true;
206 return false;
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))
215 m_tags.Clear();
216 foreach (string s in output.Split(m_lineSep, StringSplitOptions.RemoveEmptyEntries))
218 m_tags.Add(new Tag(s.Trim(), m_path));
220 return true;
222 return false;
225 public bool NewBranch(string name, Branch startPoint, Remote remote, bool bForce)
227 Executioner e = Executioner.GetExecutioner(m_path);
228 string arguments = name;
229 if (bForce)
231 arguments = arguments + " -f";
233 if (null != startPoint)
235 arguments = arguments + " " + startPoint.Name;
237 if (null != remote)
239 arguments = arguments + " --track " + remote.Name;
241 bool retval = 0 == e.Execute("git-branch", arguments);
242 UpdateBranches();
243 return retval;
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);
250 UpdateBranches();
251 return retval;
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);
258 UpdateBranches();
259 return retval;
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);
294 Git.File f;
295 if (filesMap.TryGetValue(file, out f))
297 f.SetState(front);
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();
310 if (line.Length < 3)
312 continue;
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);
325 File f;
326 if (!files.TryGetValue(line, out f))//work around git reporting files twice sometimes
328 f = new File(null, line);
329 files.Add(line, f);
331 if (front == "?")
333 f.State = FileState.Unknown;
335 else
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;
353 if (null != start)
355 args += start.ID;
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);
365 commits.Add(c);
367 return true;
369 commits = null;
370 return false;