2 using System
.Collections
.Generic
;
3 using System
.ComponentModel
;
7 using System
.Windows
.Forms
;
8 using System
.Diagnostics
;
14 public partial class Form1
: Form
16 protected List
<Git
.File
> m_files
;
17 protected OutputTextWriter m_outputWriter
;
18 Prefs m_prefs
= new Prefs();
20 ImageList m_imageList
= new ImageList();
22 protected Dictionary
<string, string> m_expandedPaths
= new Dictionary
<string, string>();
23 protected int m_selectedTypes
= -1;
24 protected Commit m_lastCommitInPage
;
25 protected Stack
<Commit
> m_topCommits
= new Stack
<Commit
>();
29 InitializeComponent();
30 //TextWriter stdout = System.Console.Out;
31 //OutputTextWriter m_outputWriter = new OutputTextWriter(m_outputArea, stdout);
32 //System.Console.SetOut(m_outputWriter);
33 m_workspaceTree
.BeforeExpand
+= new TreeViewCancelEventHandler(OnBeforeExpand
);
34 m_workspaceTree
.AfterCollapse
+= new TreeViewEventHandler(OnAfterCollapse
);
35 Executioner
.BinaryDirPath
= m_prefs
.GitDir
;
38 m_workspaceTree
.ImageList
= m_imageList
;
39 m_workspaceTree
.TreeViewNodeSorter
= new Gitrdone
.NodeSorter();
40 m_workspaceTree
.FullRowSelect
= true;
41 m_workspaceTree
.AfterSelect
+= new TreeViewEventHandler(OnNodeSelected
);
44 void OnNodeSelected(object sender
, TreeViewEventArgs e
)
46 EnableModifyButtons(m_workspaceTree
.SelectedNode
!= null);
49 protected void EnableModifyButtons(bool bEnable
)
51 m_addFileButton
.Enabled
= bEnable
;
52 m_removeFiles
.Enabled
= bEnable
;
53 m_revertFiles
.Enabled
= bEnable
;
56 void OnAfterCollapse(object sender
, TreeViewEventArgs e
)
60 m_expandedPaths
.Remove((string)e
.Node
.Tag
);
64 void OnBeforeExpand(object sender
, TreeViewCancelEventArgs e
)
66 m_workspaceTree
.SelectedNode
= e
.Node
;
67 if (Enabled
&& !m_expandedPaths
.ContainsKey((string)e
.Node
.Tag
))
69 m_expandedPaths
.Add((string)e
.Node
.Tag
, null);
73 private void PopulateImageList()
75 System
.Reflection
.Assembly a
= System
.Reflection
.Assembly
.GetExecutingAssembly();
76 System
.Resources
.ResourceManager m
= new System
.Resources
.ResourceManager("Gitrdone.Properties.Resources", a
);
77 Image im
= (System
.Drawing
.Image
)m
.GetObject("folder");
78 m_imageList
.Images
.Add("folder", im
);
80 im
= (System
.Drawing
.Image
)m
.GetObject("page");
81 m_imageList
.Images
.Add("normal", im
);
82 im
= (System
.Drawing
.Image
)m
.GetObject("page_edit");
83 m_imageList
.Images
.Add("modified", im
);
84 im
= (System
.Drawing
.Image
)m
.GetObject("page_add");
85 m_imageList
.Images
.Add("added", im
);
86 im
= (System
.Drawing
.Image
)m
.GetObject("page_delete");
87 m_imageList
.Images
.Add("delete", im
);
88 im
= (System
.Drawing
.Image
)m
.GetObject("page_error");
89 m_imageList
.Images
.Add("unmerged", im
);
90 im
= (System
.Drawing
.Image
)m
.GetObject("disconnect");
91 m_imageList
.Images
.Add("unknown", im
);
93 im
= (System
.Drawing
.Image
)m
.GetObject("page_error");
94 m_imageList
.Images
.Add("broken", im
);
95 im
= (System
.Drawing
.Image
)m
.GetObject("page_lightning");
96 m_imageList
.Images
.Add("modechanged", im
);
97 im
= (System
.Drawing
.Image
)m
.GetObject("page_copy");
98 m_imageList
.Images
.Add("copied", im
);
99 im
= (System
.Drawing
.Image
)m
.GetObject("page_go");
100 m_imageList
.Images
.Add("renamed", im
);
105 if (m_prefs
.Repos
== null)
107 m_prefs
.Repos
= new System
.Collections
.Specialized
.StringCollection();
109 object o
= m_reposCombo
.SelectedItem
;
110 m_reposCombo
.Items
.Clear();
111 foreach (string s
in m_prefs
.Repos
)
113 m_reposCombo
.Items
.Add(s
);
115 m_reposCombo
.SelectedItem
= o
;
119 void PreferencesUpdated()
121 Executioner
.BinaryDirPath
= m_prefs
.GitDir
;
125 protected bool UpdateTags()
130 protected bool UpdateBranches()
132 m_branchesCombo
.Items
.Clear();
133 foreach (Branch b
in m_currentRepo
.Branches
)
135 m_branchesCombo
.Items
.Add(b
.Name
);
137 m_branchesCombo
.SelectedItem
= m_currentRepo
.CurrentBranch
.Name
;
141 protected void SetNodeImage(TreeNode n
, Git
.File f
)
145 case FileState
.Normal
:
146 n
.ImageKey
= "normal";
147 n
.SelectedImageKey
= "normal";
149 case FileState
.Deleted
:
150 n
.ImageKey
= "delete";
151 n
.SelectedImageKey
= "delete";
153 case FileState
.Modified
:
154 n
.ImageKey
= "modified";
155 n
.SelectedImageKey
= "modified";
157 case FileState
.Unknown
:
158 n
.ImageKey
= "unknown";
159 n
.SelectedImageKey
= "unknown";
161 case FileState
.Unmerged
:
162 n
.ImageKey
= "unmerged";
163 n
.SelectedImageKey
= "unmerged";
165 case FileState
.Added
:
166 n
.ImageKey
= "added";
167 n
.SelectedImageKey
= "added";
169 case FileState
.Copied
:
170 n
.ImageKey
= "copied";
171 n
.SelectedImageKey
= "copied";
173 case FileState
.ModeChanged
:
174 n
.ImageKey
= "modechanged";
175 n
.SelectedImageKey
= "modechanged";
177 case FileState
.Broken
:
178 n
.ImageKey
= "broken";
179 n
.SelectedImageKey
= "broken";
181 case FileState
.Renamed
:
182 n
.ImageKey
= "renamed";
183 n
.SelectedImageKey
= "renamed";
186 n
.ImageKey
= "unknown";
187 n
.SelectedImageKey
= "unknown";
192 protected void AddNewFileNode(TreeNode n
, Git
.File f
)
194 TreeNode subNode
= n
.Nodes
.Add(f
.Name
, f
.Name
);
196 SetNodeImage(subNode
, f
);
199 protected TreeNode
AddNewDirNode(TreeNode n
, string subpath
, string tag
)
201 TreeNode subNode
= n
.Nodes
.Add(subpath
, subpath
);
202 subNode
.ImageIndex
= 0;
207 protected TreeNode
BuildTreePath(string path
)
209 string[] parts
= path
.Split(Repo
.DirectorySeparator
.ToCharArray());
210 TreeNode currentNode
= m_rootNode
;
211 foreach (string part
in parts
)
213 int idx
= currentNode
.Nodes
.IndexOfKey(part
);
216 currentNode
= currentNode
.Nodes
[idx
];
220 currentNode
= AddNewDirNode(currentNode
, part
, path
);
226 protected bool ResetRepoTree(Repo repo
)
228 this.Enabled
= false;
229 m_files
= repo
.ListFiles();
230 System
.Console
.WriteLine("files: " + m_files
.Count
);
231 System
.Collections
.IComparer sorter
= m_workspaceTree
.TreeViewNodeSorter
;
232 m_workspaceTree
.TreeViewNodeSorter
= null;
233 m_workspaceTree
.BeginUpdate();
234 m_workspaceTree
.Nodes
.Clear();
235 m_rootNode
= new TreeNode("root");
237 m_rootNode
.ImageIndex
= 0;
238 m_workspaceTree
.Nodes
.Add(m_rootNode
);
239 Multidict
<string, Git
.File
> dict
= new Multidict
<string, Git
.File
>();
240 foreach (Git
.File f
in m_files
)
242 if (0 != ((int)f
.State
& m_selectedTypes
))
244 dict
.Add(f
.RelativePath
, f
);
247 foreach (KeyValuePair
<string, List
<Git
.File
>> pair
in dict
)
249 TreeNode nodeToUse
= m_rootNode
;
252 nodeToUse
= BuildTreePath(pair
.Key
);
254 foreach (Git
.File f
in pair
.Value
)
256 AddNewFileNode(nodeToUse
, f
);
259 m_workspaceTree
.TreeViewNodeSorter
= sorter
;
260 m_workspaceTree
.EndUpdate();
265 private void OnPreferencesClicked(object sender
, EventArgs e
)
267 PreferencesEditor p
= new PreferencesEditor(m_prefs
);
269 PreferencesUpdated();
272 private void OnManageRepos(object sender
, EventArgs e
)
274 RepoManager m
= new RepoManager(m_prefs
);
279 private void OnRepoChanged(object sender
, EventArgs e
)
281 m_expandedPaths
.Clear();
282 if (m_reposCombo
.SelectedIndex
> -1)
284 m_currentRepo
= new Repo(m_reposCombo
.SelectedItem
.ToString());
285 if (! (ResetRepoTree(m_currentRepo
) &&
286 UpdateBranches() && UpdateTags()) )
288 MessageBox
.Show("There was an error switching to the repo.", "Error", MessageBoxButtons
.OK
, MessageBoxIcon
.Error
);
290 m_fetchCommits
.Enabled
= true;
291 m_treeStrip
.Enabled
= true;
292 m_commitsView
.Items
.Clear();
293 m_previousCommits
.Enabled
= false;
294 m_nextCommits
.Enabled
= false;
295 m_topCommits
.Clear();
296 m_lastCommitInPage
= null;
300 MessageBox
.Show("Select a repo.", "Error", MessageBoxButtons
.OK
, MessageBoxIcon
.Error
);
304 private void OnBranchChanged(object sender
, EventArgs e
)
306 if (m_branchesCombo
.SelectedIndex
> -1)
308 if (m_currentRepo
.CurrentBranch
.Name
!= m_branchesCombo
.SelectedItem
.ToString())
310 foreach (Branch b
in m_currentRepo
.Branches
)
312 if (b
.Name
== m_branchesCombo
.SelectedItem
.ToString())
314 m_currentRepo
.Checkout(b
);
317 ResetRepoTree(m_currentRepo
);
322 MessageBox
.Show("Select a branch.", "Error", MessageBoxButtons
.OK
, MessageBoxIcon
.Error
);
326 private void OnCreateBranch(object sender
, EventArgs e
)
331 private void OnMergeBranch(object sender
, EventArgs e
)
336 private void OnDeleteBranch(object sender
, EventArgs e
)
341 private void OnExit(object sender
, EventArgs e
)
346 private void OnShowNormal(object sender
, EventArgs e
)
348 if (((ToolStripButton
)sender
).Checked
)
350 m_selectedTypes
= m_selectedTypes
| (int)Git
.FileState
.Normal
;
354 m_selectedTypes
= m_selectedTypes
& (int)~Git
.FileState
.Normal
;
356 OnRefreshTree(null, null);
359 private void OnShowEdited(object sender
, EventArgs e
)
361 if (((ToolStripButton
)sender
).Checked
)
363 m_selectedTypes
= m_selectedTypes
| (int)Git
.FileState
.Modified
;
367 m_selectedTypes
= m_selectedTypes
& (int)~Git
.FileState
.Modified
;
369 OnRefreshTree(null, null);
372 private void OnShowDeleted(object sender
, EventArgs e
)
374 if (((ToolStripButton
)sender
).Checked
)
376 m_selectedTypes
= m_selectedTypes
| (int)Git
.FileState
.Deleted
;
380 m_selectedTypes
= m_selectedTypes
& (int)~Git
.FileState
.Deleted
;
382 OnRefreshTree(null, null);
385 private void OnShowOther(object sender
, EventArgs e
)
387 if (((ToolStripButton
)sender
).Checked
)
389 m_selectedTypes
= m_selectedTypes
| (int)Git
.FileState
.Modified
;
390 m_selectedTypes
= m_selectedTypes
| (int)Git
.FileState
.Unknown
;
394 m_selectedTypes
= m_selectedTypes
& (int)~Git
.FileState
.Modified
;
395 m_selectedTypes
= m_selectedTypes
& (int)~Git
.FileState
.Unknown
;
397 OnRefreshTree(null, null);
400 private void OnShowUnmerged(object sender
, EventArgs e
)
402 if (((ToolStripButton
)sender
).Checked
)
404 m_selectedTypes
= m_selectedTypes
| (int)Git
.FileState
.Unmerged
;
408 m_selectedTypes
= m_selectedTypes
& (int)~Git
.FileState
.Unmerged
;
410 OnRefreshTree(null, null);
413 protected void ExpandPath(string s
)
415 string[] parts
= s
.Split(Repo
.DirectorySeparator
.ToCharArray());
416 TreeNode currentNode
= m_rootNode
;
418 foreach (string part
in parts
)
420 int idx
= currentNode
.Nodes
.IndexOfKey(part
);
423 currentNode
= currentNode
.Nodes
[idx
];
424 currentNode
.Expand();
429 private void OnRefreshTree(object sender
, EventArgs e
)
431 if (null != m_workspaceTree
.SelectedNode
)
433 object o
= m_workspaceTree
.SelectedNode
.Tag
;
434 ResetRepoTree(m_currentRepo
);
435 this.Enabled
= false;
436 foreach (string s
in m_expandedPaths
.Keys
)
444 private void OnAddFiles(object sender
, EventArgs e
)
447 if (m_workspaceTree
.SelectedNode
.Tag
is Git
.File
)
449 Git
.File f
= (Git
.File
)m_workspaceTree
.SelectedNode
.Tag
;
450 List
<string> paths
= new List
<string>();
451 if (f
.RelativePath
.Length
> 0)
453 paths
.Add(f
.RelativePath
+ Repo
.DirectorySeparator
+ f
.Name
);
459 List
<Git
.File
> files
;
460 if (m_currentRepo
.Add(paths
, out files
))
462 Git
.File updatedFile
= files
[0];
463 if (0 != ((int)updatedFile
.State
& m_selectedTypes
))
465 m_workspaceTree
.SelectedNode
.Tag
= files
[0];
466 SetNodeImage(m_workspaceTree
.SelectedNode
, files
[0]);
473 private void OnDeleteFiles(object sender
, EventArgs e
)
476 if (m_workspaceTree
.SelectedNode
.Tag
is Git
.File
)
478 Git
.File f
= (Git
.File
)m_workspaceTree
.SelectedNode
.Tag
;
479 List
<string> paths
= new List
<string>();
480 if (f
.RelativePath
.Length
> 0)
482 paths
.Add(f
.RelativePath
+ Repo
.DirectorySeparator
+ f
.Name
);
488 List
<Git
.File
> files
;
489 if (m_currentRepo
.Remove(paths
, out files
))
491 m_workspaceTree
.SelectedNode
.Tag
= files
[0];
492 SetNodeImage(m_workspaceTree
.SelectedNode
, files
[0]);
498 private void OnRevertFiles(object sender
, EventArgs e
)
500 if (m_workspaceTree
.SelectedNode
.Tag
is Git
.File
)
502 Git
.File f
= (Git
.File
)m_workspaceTree
.SelectedNode
.Tag
;
503 List
<string> paths
= new List
<string>();
504 if (f
.RelativePath
.Length
> 0)
506 paths
.Add(f
.RelativePath
+ Repo
.DirectorySeparator
+ f
.Name
);
512 List
<Git
.File
> files
;
513 if (m_currentRepo
.Revert(paths
, out files
))
515 m_workspaceTree
.SelectedNode
.Tag
= files
[0];
516 SetNodeImage(m_workspaceTree
.SelectedNode
, files
[0]);
521 private void OnResetHard(object sender
, EventArgs e
)
523 DialogResult r
= MessageBox
.Show("Are you sure you want to revert everything you have in your working directory?",
524 "Gitrdone", MessageBoxButtons
.YesNo
, MessageBoxIcon
.Warning
);
525 if (r
== DialogResult
.Yes
)
527 m_currentRepo
.Reset(null);
528 ResetRepoTree(m_currentRepo
);
532 private void OnCopyFiles(object sender
, EventArgs e
)
537 private void OnMoveFiles(object sender
, EventArgs e
)
542 private void OnShowAdded(object sender
, EventArgs e
)
547 private void OnShowCopied(object sender
, EventArgs e
)
552 private void OnShowRenamed(object sender
, EventArgs e
)
557 private void OnShowUnmanaged(object sender
, EventArgs e
)
563 private void OnFetchCommits(object sender
, EventArgs e
)
565 List
<Commit
> commits
;
566 if (!m_currentRepo
.GetLog(null, 100, out commits
))
568 MessageBox
.Show("Could not get commits.", "Error", MessageBoxButtons
.OK
, MessageBoxIcon
.Error
);
571 m_topCommits
.Clear();
572 m_topCommits
.Push(commits
[0]);
573 FillCommitList(commits
);
576 private void FillCommitList(List
<Commit
> commits
)
578 m_commitsView
.BeginUpdate();
579 m_commitsView
.Items
.Clear();
580 foreach (Commit c
in commits
)
582 ListViewItem i
= new ListViewItem(new string[] { c.ID, c.AuthorName, c.AuthorEmail, c.Date, c.Subject }
);
584 m_commitsView
.Items
.Add(i
);
586 if (commits
.Count
> 0)
588 m_lastCommitInPage
= commits
[commits
.Count
- 1];
590 m_previousCommits
.Enabled
= m_nextCommits
.Enabled
= commits
.Count
!= 0;
591 if (m_commitsView
.Items
.Count
!= 100)
593 m_nextCommits
.Enabled
= false;
595 if (m_topCommits
.Count
< 2)
597 m_previousCommits
.Enabled
= false;
600 m_commitsView
.EndUpdate();
603 private void OnPreviousCommits(object sender
, EventArgs e
)
605 List
<Commit
> commits
;
606 Commit c
= m_topCommits
.Pop();
607 if (!m_currentRepo
.GetLog(m_topCommits
.Peek(), 100, out commits
))
609 m_nextCommits
.Enabled
= false;
612 if (commits
.Count
< 1)
614 m_previousCommits
.Enabled
= false;
618 FillCommitList(commits
);
622 private void OnNextCommits(object sender
, EventArgs e
)
624 List
<Commit
> commits
;
625 if (!m_currentRepo
.GetLog(m_lastCommitInPage
, 100, out commits
))
627 m_nextCommits
.Enabled
= false;
630 if (commits
.Count
< 1)
632 m_nextCommits
.Enabled
= false;
636 m_topCommits
.Push(commits
[0]);
637 FillCommitList(commits
);