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 public bool Revert(List
<string> paths
, out List
<File
> files
)
112 Executioner e
= Executioner
.GetExecutioner(m_path
);
114 string input
= String
.Join("\n", paths
.ToArray());
115 string output
, error
;
116 if (e
.Execute("git-add", "--add --stdin", input
, out output
, out error
) == 0)
118 return GetFiles(paths
, out files
);
123 public bool Remove(List
<string> paths
, out List
<File
> files
)
127 files
= new List
<File
>();
130 Executioner e
= Executioner
.GetExecutioner(m_path
);
131 List
<string> pathsCopy
= new List
<string>(paths
);
132 paths
[0] = " \"" + paths
[0];
133 paths
[paths
.Count
- 1] = paths
[paths
.Count
- 1] + "\"";
134 string input
= String
.Join("\" \"", paths
.ToArray());
136 if (e
.Execute("git-rm", "--cached -f " + input
) == 0)
138 return GetFiles(pathsCopy
, out files
);
144 public bool Checkout(Treeish t
)
150 Executioner e
= Executioner
.GetExecutioner(m_path
);
151 return 0 == e
.Execute("git-checkout", t
.ID
);
154 public bool Checkout(Tag t
, string newBranchName
)
160 Executioner e
= Executioner
.GetExecutioner(m_path
);
161 if (0 == e
.Execute("git-checkout", "-b " + newBranchName
+ " " + t
.Name
))
169 protected bool UpdateBranches()
171 Executioner e
= Executioner
.GetExecutioner(m_path
, false);
172 string output
, error
;
173 if (0 == e
.Execute("git-branch", "", "", out output
, out error
))
176 foreach (string s
in output
.Split(m_lineSep
, StringSplitOptions
.RemoveEmptyEntries
))
178 string branchName
= s
.Trim();
179 if (branchName
.StartsWith("*"))
181 branchName
= branchName
.Substring(2);
182 branchName
= branchName
.Trim();
183 m_CurrentBranch
= new Branch(m_path
, branchName
);
184 m_branches
.Add(m_CurrentBranch
);
188 m_branches
.Add(new Branch(m_path
, branchName
));
196 protected bool UpdateTags()
198 Executioner e
= Executioner
.GetExecutioner(m_path
, false);
199 string output
= null, error
= null;
200 if (0 == e
.Execute("git-rev-parse", "--symbolic --tags", "", out output
, out error
))
203 foreach (string s
in output
.Split(m_lineSep
, StringSplitOptions
.RemoveEmptyEntries
))
205 m_tags
.Add(new Tag(s
.Trim(), m_path
));
212 public bool NewBranch(string name
, Branch startPoint
, Remote remote
, bool bForce
)
214 Executioner e
= Executioner
.GetExecutioner(m_path
);
215 string arguments
= name
;
218 arguments
= arguments
+ " -f";
220 if (null != startPoint
)
222 arguments
= arguments
+ " " + startPoint
.Name
;
226 arguments
= arguments
+ " --track " + remote
.Name
;
228 bool retval
= 0 == e
.Execute("git-branch", arguments
);
233 public bool RenameBranch(Branch b
, string newName
, bool bForce
)
235 Executioner e
= Executioner
.GetExecutioner(m_path
);
236 bool retval
= 0 == e
.Execute("git-branch", bForce
? "-M " : "-m " + b
.Name
+ " " + newName
);
241 public bool DeleteBranch(Branch b
, bool bForce
)
243 Executioner e
= Executioner
.GetExecutioner(m_path
);
244 bool retval
= 0 == e
.Execute("git-branch", bForce
? "-D " : "-d " + b
.Name
);
249 public List
<File
> ListFiles()
251 Executioner e
= Executioner
.GetExecutioner(m_path
, true);
252 string output
, error
;
253 Dictionary
<string, File
> files
= new Dictionary
<string, File
>();
254 if (0 == e
.Execute("git-ls-files", "-c -d -m -o -k -t -z", "", out output
, out error
))
256 ParseLSOutput(output
, files
);
258 UpdateFromIndex(files
, "");
259 return new List
<File
>(files
.Values
);
262 private void UpdateFromIndex(Dictionary
<string, File
> filesMap
, string paths
)
264 Executioner e
= Executioner
.GetExecutioner(m_path
, true);
265 string output
, error
;
266 if (0 == e
.Execute("git-diff-index", "-B -M -C -z --name-status HEAD " + paths
, "", out output
, out error
))
268 string[] lines
= output
.Split("\0".ToCharArray());
269 for (int i
= 0; i
< lines
.Length
- 1; i
+= 2)
271 string front
= lines
[i
][0].ToString();
272 string file
= lines
[i
+ 1].Trim();
273 if (file
.StartsWith("\""))
275 file
= file
.Substring(1);
277 if (file
.EndsWith("\""))
279 file
= file
.Substring(0, file
.Length
- 1);
282 if (filesMap
.TryGetValue(file
, out f
))
290 private void ParseLSOutput(string output
, Dictionary
<string, File
> files
)
292 string[] lines
= output
.Split("\0".ToCharArray());
293 System
.Console
.WriteLine("path: " + m_path
+ " files: " + lines
.Length
);
294 foreach (string oneline
in lines
)
296 string line
= oneline
.Trim();
302 string front
= line
[0].ToString();
303 line
= line
.Substring(2);
304 if (line
.StartsWith("\""))
306 line
= line
.Substring(1);
308 if (line
.EndsWith("\""))
310 line
= line
.Substring(0, line
.Length
- 1);
313 if (!files
.TryGetValue(line
, out f
))//work around git reporting files twice sometimes
315 f
= new File(null, line
);
320 f
.State
= FileState
.Unknown
;
324 f
.State
= FileState
.Normal
;