├── .gitignore
├── ClassAppHelper.cs
├── ClassArguments.cs
├── ClassBranches.cs
├── ClassCommandLine.cs
├── ClassCommit.cs
├── ClassCommits.cs
├── ClassConfig.cs
├── ClassDiff.cs
├── ClassException.cs
├── ClassExecute.cs
├── ClassGit.cs
├── ClassGitDirectory.cs
├── ClassGlobals.cs
├── ClassHelp.cs
├── ClassHttpsPasswd.cs
├── ClassMerge.cs
├── ClassPortableSettings.cs
├── ClassPutty.cs
├── ClassRemotes.cs
├── ClassRepo.cs
├── ClassRepos.cs
├── ClassSSH.cs
├── ClassStatus.cs
├── ClassTabCheck.cs
├── ClassTool.cs
├── ClassURL.cs
├── ClassUtils.cs
├── ClassVersion.cs
├── ClassView.cs
├── ClassWin32.cs
├── ClassWinGeometry.cs
├── ClassWorkspace.cs
├── FormAbout.Designer.cs
├── FormAbout.cs
├── FormAbout.resx
├── FormChangelistFilter.Designer.cs
├── FormChangelistFilter.cs
├── FormChangelistFilter.resx
├── FormCommit.Designer.cs
├── FormCommit.cs
├── FormCommit.resx
├── FormCommitMerge.Designer.cs
├── FormCommitMerge.cs
├── FormCommitMerge.resx
├── FormCustomToolArgs.Designer.cs
├── FormCustomToolArgs.cs
├── FormCustomToolArgs.resx
├── FormCustomizeTools.Designer.cs
├── FormCustomizeTools.cs
├── FormCustomizeTools.resx
├── FormDeleteBranch.Designer.cs
├── FormDeleteBranch.cs
├── FormDeleteBranch.resx
├── FormDeleteRepo.Designer.cs
├── FormDeleteRepo.cs
├── FormDeleteRepo.resx
├── FormDiffMissing.Designer.cs
├── FormDiffMissing.cs
├── FormDiffMissing.resx
├── FormDownload.Designer.cs
├── FormDownload.cs
├── FormDownload.resx
├── FormEditTools.Designer.cs
├── FormEditTools.cs
├── FormEditTools.resx
├── FormGitRun.Designer.cs
├── FormGitRun.cs
├── FormGitRun.resx
├── FormHttps.Designer.cs
├── FormHttps.cs
├── FormHttps.resx
├── FormHttpsAuth.Designer.cs
├── FormHttpsAuth.cs
├── FormHttpsAuth.resx
├── FormLog.Designer.cs
├── FormLog.cs
├── FormLog.resx
├── FormMain.Designer.cs
├── FormMain.cs
├── FormMain.resx
├── FormMergeBranch.Designer.cs
├── FormMergeBranch.cs
├── FormMergeBranch.resx
├── FormMergeMissing.Designer.cs
├── FormMergeMissing.cs
├── FormMergeMissing.resx
├── FormNewBranch.Designer.cs
├── FormNewBranch.cs
├── FormNewBranch.resx
├── FormNewRepoScan.Designer.cs
├── FormNewRepoScan.cs
├── FormNewRepoScan.resx
├── FormNewRepoScanAdd.Designer.cs
├── FormNewRepoScanAdd.cs
├── FormNewRepoScanAdd.resx
├── FormNewRepoScanProgress.Designer.cs
├── FormNewRepoScanProgress.cs
├── FormNewRepoScanProgress.resx
├── FormNewRepoStep1.Designer.cs
├── FormNewRepoStep1.cs
├── FormNewRepoStep1.resx
├── FormNewRepoStep2.Designer.cs
├── FormNewRepoStep2.cs
├── FormNewRepoStep2.resx
├── FormPathToGit.Designer.cs
├── FormPathToGit.cs
├── FormPathToGit.resx
├── FormRecreateRepos.Designer.cs
├── FormRecreateRepos.cs
├── FormRecreateRepos.resx
├── FormRemoteAddEdit.Designer.cs
├── FormRemoteAddEdit.cs
├── FormRemoteAddEdit.resx
├── FormRemoteEdit.Designer.cs
├── FormRemoteEdit.cs
├── FormRemoteEdit.resx
├── FormRename.Designer.cs
├── FormRename.cs
├── FormRename.resx
├── FormRepoEdit.Designer.cs
├── FormRepoEdit.cs
├── FormRepoEdit.resx
├── FormReset.Designer.cs
├── FormReset.cs
├── FormReset.resx
├── FormRevisionHistory.Designer.cs
├── FormRevisionHistory.cs
├── FormRevisionHistory.resx
├── FormSSH.Designer.cs
├── FormSSH.cs
├── FormSSH.resx
├── FormSettings.Designer.cs
├── FormSettings.cs
├── FormSettings.resx
├── FormShowChangelist.Designer.cs
├── FormShowChangelist.cs
├── FormShowChangelist.resx
├── FormStash.Designer.cs
├── FormStash.cs
├── FormStash.resx
├── FormSwitchToBranch.Designer.cs
├── FormSwitchToBranch.cs
├── FormSwitchToBranch.resx
├── FormUnstash.Designer.cs
├── FormUnstash.cs
├── FormUnstash.resx
├── GitForce.csproj
├── GitForce.sln
├── ListBoxEx.cs
├── ListViewEx.cs
├── ListViewReorderEx.cs
├── Main.Left.Panels
├── PanelView.Designer.cs
├── PanelView.cs
└── PanelView.resx
├── Main.Right.Panels
├── PanelBranches.Designer.cs
├── PanelBranches.cs
├── PanelBranches.resx
├── PanelCommits.Designer.cs
├── PanelCommits.cs
├── PanelCommits.resx
├── PanelRepos.Designer.cs
├── PanelRepos.cs
├── PanelRepos.resx
├── PanelRevlist.Designer.cs
├── PanelRevlist.cs
└── PanelRevlist.resx
├── Program.cs
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── README.md
├── Release.py
├── Repo.Edit.Panels
├── ControlGitconfig.Designer.cs
├── ControlGitconfig.cs
├── ControlGitconfig.resx
├── ControlGitignore.Designer.cs
├── ControlGitignore.cs
├── ControlGitignore.resx
├── ControlLocal.Designer.cs
├── ControlLocal.cs
├── ControlLocal.resx
├── ControlRemotes.Designer.cs
├── ControlRemotes.cs
├── ControlRemotes.resx
├── ControlUser.Designer.cs
├── ControlUser.cs
└── ControlUser.resx
├── Resources
├── .gitattributes
├── App
│ ├── 1475_Text Balloon_48x48.ico
│ ├── eye.png
│ ├── file_missing.png
│ ├── git.ico
│ ├── pulldown.png
│ ├── update.gif
│ └── world.png
├── Artwork
│ ├── GitForceLogo-large.lds
│ ├── GitForceLogo-small.lds
│ ├── gif
│ │ └── GitForceLogo-large.gif
│ ├── png
│ │ ├── GitForceLogo-dl.png
│ │ ├── GitForceLogo-small.png
│ │ └── GitForceLogo.png
│ └── readme.txt
├── Branch
│ ├── 112_RightArrowLong_Green_16x16_72.png
│ ├── 112_RightArrowLong_Grey_16x16_72.png
│ └── branch.bmp
├── Changelist
│ ├── 112_DownArrowShort_Blue_16x16_72.png
│ ├── 112_UpArrowShort_Blue_16x16_72.png
│ ├── Change0.ico
│ ├── Change1.ico
│ ├── Journal.ico
│ ├── search.ico
│ └── xsearch.ico
├── File
│ ├── document.revert.png
│ ├── document_a4_add.png
│ ├── document_a4_remove.png
│ ├── document_letter_forward.png
│ ├── documents_add.png
│ ├── download.png
│ ├── pencil.png
│ ├── remove.png
│ └── upload.png
├── PuTTY
│ ├── PAGEANT.ICO
│ ├── PUTTYGEN.ICO
│ ├── pageant.exe
│ ├── plink.exe
│ └── puttygen.exe
├── Repo
│ ├── Repo0.ico
│ ├── Repo1.ico
│ ├── Repo2.ico
│ └── Repo3.ico
├── SSH
│ └── git-ssh-helper.sh
├── Toolstrip
│ ├── Change0.ico
│ ├── Gear.ico
│ ├── branch.bmp
│ ├── eventlogError.ico
│ ├── key.ico
│ └── keys.ico
├── Tree
│ ├── TreeIconA.ico
│ ├── TreeIconC.ico
│ ├── TreeIconD.ico
│ ├── TreeIconDB.ico
│ ├── TreeIconFC.ico
│ ├── TreeIconFCM.ico
│ ├── TreeIconFF.ico
│ ├── TreeIconFO.ico
│ ├── TreeIconFOM.ico
│ ├── TreeIconM.ico
│ ├── TreeIconQ.ico
│ ├── TreeIconR.ico
│ ├── TreeIconU.ico
│ └── TreeIconX.ico
└── View
│ ├── 112_RefreshArrow_Blue.ico
│ ├── Scroll.ico
│ └── openHS.bmp
├── RichTextBoxEx.cs
├── Settings.Panels
├── ControlAliases.Designer.cs
├── ControlAliases.cs
├── ControlAliases.resx
├── ControlCommits.Designer.cs
├── ControlCommits.cs
├── ControlCommits.resx
├── ControlDiff.Designer.cs
├── ControlDiff.cs
├── ControlDiff.resx
├── ControlDoubleClick.Designer.cs
├── ControlDoubleClick.cs
├── ControlDoubleClick.resx
├── ControlFiles.Designer.cs
├── ControlFiles.cs
├── ControlFiles.resx
├── ControlGitconfig.Designer.cs
├── ControlGitconfig.cs
├── ControlGitconfig.resx
├── ControlGitignore.Designer.cs
├── ControlGitignore.cs
├── ControlGitignore.resx
├── ControlGlobal.Designer.cs
├── ControlGlobal.cs
├── ControlGlobal.resx
├── ControlMerge.Designer.cs
├── ControlMerge.cs
├── ControlMerge.resx
├── ControlOptions.Designer.cs
├── ControlOptions.cs
├── ControlOptions.resx
├── ControlSpecifications.Designer.cs
├── ControlSpecifications.cs
├── ControlSpecifications.resx
├── ControlSsl.Designer.cs
├── ControlSsl.cs
├── ControlSsl.resx
├── ControlStatus.Designer.cs
├── ControlStatus.cs
├── ControlStatus.resx
├── ControlUser.Designer.cs
├── ControlUser.cs
├── ControlUser.resx
├── ControlViewEdit.Designer.cs
├── ControlViewEdit.cs
└── ControlViewEdit.resx
├── TabEx.cs
├── TextBoxEx.cs
├── TreeViewEx.cs
├── UserControlEditFile.Designer.cs
├── UserControlEditFile.cs
├── UserControlEditFile.resx
├── UserControlEditGitignore.Designer.cs
├── UserControlEditGitignore.cs
├── UserControlEditGitignore.resx
├── UserControlRemoteEdit.Designer.cs
├── UserControlRemoteEdit.cs
├── UserControlRemoteEdit.resx
├── UserControlRemotesEdit.Designer.cs
├── UserControlRemotesEdit.cs
├── UserControlRemotesEdit.resx
├── app.config
└── git.ico
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 | [Dd]ebug/
46 | [Rr]elease/
47 | *_i.c
48 | *_p.c
49 | *.ilk
50 | *.meta
51 | *.obj
52 | *.pch
53 | *.pdb
54 | *.pgc
55 | *.pgd
56 | *.rsp
57 | *.sbr
58 | *.tlb
59 | *.tli
60 | *.tlh
61 | *.tmp
62 | *.vspscc
63 | .builds
64 | *.dotCover
65 |
66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this
67 | #packages/
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 |
76 | # Visual Studio profiler
77 | *.psess
78 | *.vsp
79 |
80 | # ReSharper is a .NET coding add-in
81 | _ReSharper*
82 |
83 | # Installshield output folder
84 | [Ee]xpress
85 |
86 | # DocProject is a documentation generator add-in
87 | DocProject/buildhelp/
88 | DocProject/Help/*.HxT
89 | DocProject/Help/*.HxC
90 | DocProject/Help/*.hhc
91 | DocProject/Help/*.hhk
92 | DocProject/Help/*.hhp
93 | DocProject/Help/Html2
94 | DocProject/Help/html
95 |
96 | # Click-Once directory
97 | publish
98 |
99 | # Others
100 | [Bb]in
101 | [Oo]bj
102 | sql
103 | TestResults
104 | *.Cache
105 | ClientBin
106 | stylecop.*
107 | ~$*
108 | *.dbmdl
109 | Generated_Code #added for RIA/Silverlight projects
110 |
111 | # VS 2012 upgrade files
112 | UpgradeLog.htm
113 | backup/*
114 |
115 | # Backup & report files from converting an old project file to a newer
116 | # Visual Studio version. Backup files are not needed, because we have git ;-)
117 | _UpgradeReport_Files/
118 | Backup*/
119 | UpgradeLog*.XML
120 |
121 |
122 |
123 | ############
124 | ## Windows
125 | ############
126 |
127 | # Windows image file caches
128 | Thumbs.db
129 |
130 | # Folder config file
131 | Desktop.ini
132 |
133 |
134 | #############
135 | ## Python
136 | #############
137 |
138 | *.py[co]
139 |
140 | # Packages
141 | *.egg
142 | *.egg-info
143 | dist
144 | build
145 | eggs
146 | parts
147 | bin
148 | var
149 | sdist
150 | develop-eggs
151 | .installed.cfg
152 |
153 | # Installer logs
154 | pip-log.txt
155 |
156 | # Unit test / coverage reports
157 | .coverage
158 | .tox
159 |
160 | #Translations
161 | *.mo
162 |
163 | #Mr Developer
164 | .mr.developer.cfg
165 |
166 | # Mac crap
167 | .DS_Store
168 |
--------------------------------------------------------------------------------
/ClassAppHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 |
6 | namespace GitForce
7 | {
8 | ///
9 | /// Structure describing application helper programs (Diff, Merge)
10 | ///
11 | public struct AppHelper : IComparable
12 | {
13 | ///
14 | /// User-friendly name of an application helper tool
15 | ///
16 | public readonly string Name;
17 |
18 | ///
19 | /// Full path/name to the tool
20 | ///
21 | public readonly string Path;
22 |
23 | ///
24 | /// Arguments needed when executing the tool for a particular purpose
25 | ///
26 | public readonly string Args;
27 |
28 | ///
29 | /// Constructor that simply assigns fields
30 | ///
31 | public AppHelper(string appName, string appPath, string appArgs)
32 | {
33 | Name = appName;
34 | Path = appPath;
35 | Args = appArgs;
36 | }
37 |
38 | ///
39 | /// Constructor that deserialize fields into a new structure
40 | ///
41 | public AppHelper(string appCombined)
42 | {
43 | Name = string.Empty;
44 | Path = appCombined;
45 | Args = string.Empty;
46 | string[] parts = appCombined.Split('\t');
47 | if (parts.Length == 3)
48 | {
49 | Name = parts[0];
50 | Path = parts[1];
51 | Args = parts[2];
52 | }
53 | }
54 |
55 | ///
56 | /// ToString override returns serialized fields
57 | ///
58 | public override string ToString()
59 | {
60 | return Name + '\t' + Path + '\t' + Args;
61 | }
62 |
63 | ///
64 | /// Implements comparator
65 | ///
66 | public int CompareTo(AppHelper other)
67 | {
68 | return other.Name.CompareTo(Name);
69 | }
70 |
71 | ///
72 | /// Given a list of candidate programs, return only those that actually exist
73 | ///
74 | public static List Scan(List candidates)
75 | {
76 | return (from appHelper in candidates
77 | let path = appHelper.Path
78 | where File.Exists(path)
79 | select appHelper).ToList();
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/ClassArguments.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.Specialized;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace GitForce
6 | {
7 | ///
8 | /// Arguments class
9 | ///
10 | public class Arguments
11 | {
12 | // Variables
13 | private readonly StringDictionary parameters;
14 | private readonly List unassociated = new List();
15 |
16 | // Constructor
17 | public Arguments(string[] args)
18 | {
19 | parameters = new StringDictionary();
20 | Regex spliter = new Regex(@"^-{1,2}|^/|=|:", RegexOptions.IgnoreCase | RegexOptions.Compiled);
21 | Regex remover = new Regex(@"^['""]?(.*?)['""]?$", RegexOptions.IgnoreCase | RegexOptions.Compiled);
22 | string parameter = null;
23 | string[] parts;
24 |
25 | // Valid parameters forms:
26 | // {-,/,--}param{ ,=,:}((",')value(",'))
27 | // Examples: -param1 value1 --param2 /param3:"Test-:-work" /param4=happy -param5 '--=nice=--'
28 | foreach (string txt in args)
29 | {
30 | // Look for new parameters (-,/ or --) and a possible enclosed value (=,:)
31 | parts = spliter.Split(txt, 3);
32 | switch (parts.Length)
33 | {
34 | // Found a value (for the last parameter found (space separator))
35 | case 1:
36 | if (parameter != null)
37 | {
38 | if (!parameters.ContainsKey(parameter))
39 | {
40 | parts[0] = remover.Replace(parts[0], "$1");
41 | parameters.Add(parameter, parts[0]);
42 | }
43 | parameter = null;
44 | }
45 | else
46 | {
47 | // No parameter waiting for a value
48 | unassociated.Add(parts[0]);
49 | }
50 | break;
51 | // Found just a parameter
52 | case 2:
53 | // The last parameter is still waiting. With no value, set it to true.
54 | if (parameter != null)
55 | {
56 | if (!parameters.ContainsKey(parameter)) parameters.Add(parameter, "true");
57 | }
58 | parameter = parts[1];
59 | break;
60 | // Parameter with enclosed value
61 | case 3:
62 | // The last parameter is still waiting. With no value, set it to true.
63 | if (parameter != null)
64 | {
65 | if (!parameters.ContainsKey(parameter)) parameters.Add(parameter, "true");
66 | }
67 | parameter = parts[1];
68 | // Remove possible enclosing characters (",')
69 | if (!parameters.ContainsKey(parameter))
70 | {
71 | parts[2] = remover.Replace(parts[2], "$1");
72 | parameters.Add(parameter, parts[2]);
73 | }
74 | parameter = null;
75 | break;
76 | }
77 | }
78 | // In case a parameter is still waiting
79 | if (parameter != null)
80 | {
81 | if (!parameters.ContainsKey(parameter)) parameters.Add(parameter, "true");
82 | }
83 | }
84 |
85 | // Retrieve a parameter value if it exists
86 | public string this[string param]
87 | {
88 | get
89 | {
90 | return (parameters[param]);
91 | }
92 | }
93 | // Returns all arguments not associated with any --parameter
94 | public List GetUnassociatedArgs()
95 | {
96 | return unassociated;
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/ClassBranches.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace GitForce
5 | {
6 | ///
7 | /// List of branches for the current repo, and a set of functions to operate on them
8 | ///
9 | [Serializable]
10 | public class ClassBranches
11 | {
12 | ///
13 | /// Name of the current branch
14 | ///
15 | public string Current;
16 |
17 | ///
18 | /// List of local branches by their name
19 | ///
20 | public readonly List Local = new List();
21 |
22 | ///
23 | /// List of remote branches by their name
24 | ///
25 | public readonly List Remote = new List();
26 |
27 | ///
28 | /// Refresh the list of branches and assign local and remote
29 | ///
30 | public void Refresh()
31 | {
32 | Local.Clear();
33 | Remote.Clear();
34 | Current = null;
35 |
36 | if (App.Repos.Current != null)
37 | {
38 | ExecResult result = App.Repos.Current.RunCmd("branch -a");
39 | if (result.Success())
40 | {
41 | string[] response = result.stdout.Split((Environment.NewLine).ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
42 | foreach (string s in response)
43 | {
44 | // Recognize current branch - it is marked by an asterisk
45 | if (s[0] == '*')
46 | Current = s.Replace("*", " ").Trim();
47 |
48 | // Detect if a branch is local or remote and add it to the appropriate list
49 | if (s.Contains(" remotes/"))
50 | Remote.Add(s.Replace(" remotes/", "").Trim());
51 | else
52 | Local.Add(s.Replace("*", " ").Trim());
53 | }
54 | }
55 | }
56 | }
57 |
58 | ///
59 | /// Switch to a named branch
60 | ///
61 | public bool SwitchTo(string name)
62 | {
63 | // Make sure the given branch name is a valid local branch
64 | if (!string.IsNullOrEmpty(name) && Local.IndexOf(name) >= 0)
65 | {
66 | ExecResult result = App.Repos.Current.RunCmd("checkout " + name);
67 | return result.Success();
68 | }
69 | return false;
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/ClassCommit.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace GitForce
6 | {
7 | ///
8 | /// Class describing and working on one commit
9 | /// A commit is a set of files grouped together under one node
10 | ///
11 | [Serializable]
12 | public class ClassCommit
13 | {
14 | ///
15 | /// List of git files stored under this commit.
16 | /// Files have a path relative to the repo root.
17 | ///
18 | public List Files = new List();
19 |
20 | ///
21 | /// User description text of a commit
22 | ///
23 | public string Description;
24 |
25 | public string DescriptionTitle
26 | {
27 | get
28 | {
29 | if (Description == null) return null;
30 | var pos = Description.IndexOfAny(new[] { '\n', '\r' });
31 | if (pos == -1) pos = Description.Length;
32 | return Description.Substring(0, pos);
33 | }
34 |
35 | set
36 | {
37 | if (Description == null)
38 | {
39 | Description = value;
40 | return;
41 | }
42 |
43 | var pos = Description.IndexOfAny(new[] { '\n', '\r' });
44 | if (pos == -1)
45 | {
46 | Description = value;
47 | }
48 | else
49 | {
50 | Description = value + Description.Substring(pos);
51 | }
52 | }
53 | }
54 |
55 | ///
56 | /// Is this commit a default one (not a user added)
57 | /// Default commit cannot be deleted or renamed.
58 | ///
59 | public bool IsDefault;
60 |
61 | ///
62 | /// Is this commint node collapsed in the commits tree
63 | ///
64 | public bool IsCollapsed;
65 |
66 | ///
67 | /// Create a commit with the given description
68 | ///
69 | public ClassCommit(string desc)
70 | {
71 | Description = desc;
72 | }
73 |
74 | ///
75 | /// ToString override returns the commit description
76 | ///
77 | public override string ToString()
78 | {
79 | return Description;
80 | }
81 |
82 | ///
83 | /// Add a set of files to the commit list.
84 | /// Do not create any duplicates!
85 | ///
86 | public void AddFiles(List newFiles)
87 | {
88 | Files = Files.Union(newFiles).ToList();
89 | Files.Sort(); // Keep the list sorted
90 | }
91 |
92 | ///
93 | /// Remove all files listed from our list of files.
94 | /// Any file on that list may or may not appear on this commit list.
95 | ///
96 | public void Prune(List outlaws)
97 | {
98 | Files = Files.Except(outlaws).ToList();
99 | Files.Sort(); // Keep the list sorted
100 | }
101 |
102 | ///
103 | /// Renew the existing list of files by keeping only those that exist in the
104 | /// given list. Return the given list trimmed by files which are now "taken".
105 | ///
106 | public List Renew(List allFiles)
107 | {
108 | Files = Files.Intersect(allFiles).ToList();
109 | Files.Sort(); // Keep the list sorted
110 | return allFiles.Except(Files).ToList();
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/ClassCommits.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace GitForce
6 | {
7 | ///
8 | /// Class describing and working on a set of commits.
9 | ///
10 | [Serializable]
11 | public class ClassCommits
12 | {
13 | ///
14 | /// A bundle is a list of commits.
15 | ///
16 | public readonly List Bundle = new List();
17 |
18 | ///
19 | /// Constructor for list of commits - always create at least one (empty) commit named "Default"
20 | ///
21 | public ClassCommits()
22 | {
23 | Bundle.Add(new ClassCommit("Default"));
24 | Bundle[0].IsDefault = true;
25 | }
26 |
27 | ///
28 | /// Add a new commit bundle to the list
29 | ///
30 | public void NewBundle(string description, List files)
31 | {
32 | // Remove all files listed from every bundle
33 | foreach (var c in Bundle)
34 | c.Prune(files);
35 |
36 | // Add a new bundle with these files
37 | ClassCommit commit = new ClassCommit(description);
38 | commit.AddFiles(files);
39 | Bundle.Add(commit);
40 | }
41 |
42 | ///
43 | /// Move or add each file in the list of files to a specified bundle.
44 | /// Files in that list that are present in any other bundle will be moved.
45 | ///
46 | public void MoveOrAdd(ClassCommit bundle, List files)
47 | {
48 | // Remove all listed files from any bundle in which they might appear
49 | foreach (var c in Bundle)
50 | c.Prune(files);
51 |
52 | // Add listed files to a named bundle
53 | bundle.AddFiles(files);
54 | }
55 |
56 | ///
57 | /// Rebuild the list of files by using only the files from the given list
58 | ///
59 | public void Rebuild(List files)
60 | {
61 | files = Bundle.Aggregate(files, (current, c) => c.Renew(current));
62 |
63 | // Assign the remaining files to the first commit ("Default")
64 | Bundle[0].AddFiles(files);
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ClassConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GitForce
4 | {
5 | ///
6 | /// Class Config gets and sets values of either global git configuration or a local repository
7 | ///
8 | public static class ClassConfig
9 | {
10 | ///
11 | /// Sets or removes a global git configuration value.
12 | /// If the value is null or empty string, the key will be removed (unset).
13 | ///
14 | public static void SetGlobal(string key, string value)
15 | {
16 | string setkey = string.IsNullOrEmpty(value) ? "--unset " : "";
17 | string val = string.IsNullOrEmpty(value) ? "" : " \"" + value + "\"";
18 | string cmd = setkey + key + val;
19 |
20 | if (ClassGit.Run("config --global " + cmd).Success() == false)
21 | App.PrintLogMessage("Error setting global git config parameter!", MessageType.Error);
22 | }
23 |
24 | ///
25 | /// Sets or removes a local git configuration value.
26 | /// If the value is null or empty string, the key will be removed (unset).
27 | ///
28 | public static void SetLocal(ClassRepo repo, string key, string value)
29 | {
30 | string setkey = string.IsNullOrEmpty(value) ? "--unset " : "";
31 | string val = string.IsNullOrEmpty(value) ? "" : " \"" + value + "\"";
32 | string cmd = setkey + key + val;
33 |
34 | if (repo.Run("config --local " + cmd).Success() == false)
35 | App.PrintLogMessage("Error setting local git config parameter!", MessageType.Error);
36 | }
37 |
38 | ///
39 | /// Returns a value of a global git configuration key
40 | ///
41 | public static string GetGlobal(string key)
42 | {
43 | ExecResult result = ClassGit.Run("config --global --get " + key);
44 | if (result.Success())
45 | return result.stdout;
46 |
47 | App.PrintLogMessage("Error getting global git config parameter!", MessageType.Error);
48 | return String.Empty;
49 | }
50 |
51 | ///
52 | /// Returns a value of a local git configuration key
53 | ///
54 | public static string GetLocal(ClassRepo repo, string key)
55 | {
56 | ExecResult result = repo.Run("config --local --get " + key);
57 | if (result.Success())
58 | return result.stdout;
59 |
60 | App.PrintLogMessage("Error getting local git config parameter!", MessageType.Error);
61 | return string.Empty;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/ClassException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace GitForce
4 | {
5 | public class ClassException : Exception
6 | {
7 | private readonly string msg;
8 |
9 | public override string Message
10 | {
11 | get { return msg; }
12 | }
13 |
14 | public ClassException(string message)
15 | {
16 | msg = message;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/ClassGlobals.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Drawing;
3 |
4 | namespace GitForce
5 | {
6 | ///
7 | /// Class containing global variables used by several parts of the program.
8 | ///
9 | static class ClassGlobals
10 | {
11 | ///
12 | /// Application cached list of available fixed-width fonts
13 | ///
14 | public static readonly List Fonts = new List();
15 |
16 | ///
17 | /// List of temporary files that need to be deleted on app exit
18 | ///
19 | public static readonly List TempFiles = new List();
20 |
21 | ///
22 | /// The function that actually removes all temp files from the list
23 | ///
24 | public static void RemoveTempFiles()
25 | {
26 | foreach (var tempFile in TempFiles)
27 | {
28 | ClassUtils.DeleteFile(tempFile);
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ClassHelp.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 |
4 | namespace GitForce
5 | {
6 | ///
7 | /// Contains the code to handle various help links and access to the online help
8 | ///
9 | static class ClassHelp
10 | {
11 | ///
12 | /// Dictionary containing the translation of help topics to the web pages
13 | ///
14 | private static readonly Dictionary Webhelp = new Dictionary
15 | {
16 | {"Home", @"https://sites.google.com/site/gitforcetool"},
17 | {"Getting Started", @"https://sites.google.com/site/gitforcetool/getting-started"},
18 | {"Edit Tools", @"https://sites.google.com/site/gitforcetool/help/custom-tools"},
19 | {"HTTPS Authentication", @"https://confluence.atlassian.com/fisheye/permanent-authentication-for-git-repositories-over-http-s-298977121.html"},
20 | {"SSH Windows", @"https://sites.google.com/site/gitforcetool/help/ssh"},
21 | {"Workspace", @"https://sites.google.com/site/gitforcetool/help/workspaces"},
22 | {"Update Check", @"https://github.com/gdevic/GitForce/releases"},
23 | {"Download", @"https://github.com/gdevic/GitForce/releases"},
24 | {"Discussion", @"https://sourceforge.net/p/gitforce/discussion"},
25 | {"GPL", @"http://www.gnu.org/licenses/gpl.html"},
26 | {"BaltazarStudios", @"https://www.baltazarstudios.com" }
27 | };
28 |
29 | ///
30 | /// Given the topic, open the relevant help page online
31 | ///
32 | public static void Handler(string topic)
33 | {
34 | if (Webhelp.ContainsKey(topic))
35 | {
36 | if (ClassUtils.IsMono())
37 | Process.Start("xdg-open", Webhelp[topic]);
38 | else
39 | Process.Start(Webhelp[topic]);
40 | }
41 | else
42 | {
43 | App.PrintStatusMessage("Internal Error: Please report that `topic " + topic + "` not found!", MessageType.Error);
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/ClassHttpsPasswd.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace GitForce
5 | {
6 | ///
7 | /// Manages git HTTPS password helper file
8 | ///
9 | public class ClassHttpsPasswd
10 | {
11 | ///
12 | /// Constructor creates a shell executable file that echoes the PASSWORD
13 | /// environment variable when called. When GIT_ASKPASS is present, Git
14 | /// obtains a password for its HTTPS operations by calling it.
15 | ///
16 | public ClassHttpsPasswd()
17 | {
18 | // WAR: Do a different kind of shell script dependent on the OS)
19 | string pathPasswordBatchHelper;
20 | if (ClassUtils.IsMono())
21 | {
22 | // Mono: Use the Shell script which tests if $PASSWORD is defined and echoes it,
23 | // and if not defined, it calls GitForce application with a special argument that opens
24 | // only password dialog
25 | pathPasswordBatchHelper = Path.Combine(App.AppHome, "passwd.sh");
26 | File.WriteAllText(pathPasswordBatchHelper, "#!/bin/sh" + Environment.NewLine +
27 | "if [ \"$PASSWORD\" = \"\" ]; then" + Environment.NewLine +
28 | App.AppPath + " --passwd" + Environment.NewLine +
29 | "else" + Environment.NewLine +
30 | "echo $PASSWORD" + Environment.NewLine +
31 | "fi" );
32 | // Set the execute bit
33 | if (Exec.Run("chmod", "+x " + pathPasswordBatchHelper).Success() == false)
34 | App.PrintLogMessage("ClassHttpsPasswd: Unable to chmod +x on " + pathPasswordBatchHelper, MessageType.Error);
35 | }
36 | else
37 | {
38 | // Windows: Use the CMD BAT script
39 | // Note: Using "App.AppHome" directory to host the batch helper file
40 | // fails on XP where that directory has spaces in the name ("Documents and Settings")
41 | // which git cannot handle in this context. Similarly, git will fail with
42 | // any other path that contains a space.
43 | // This redirection is used to provide the password in an automated way.
44 | pathPasswordBatchHelper = Path.Combine(Path.GetTempPath(), "passwd.bat");
45 | File.WriteAllText(pathPasswordBatchHelper, "@echo %PASSWORD%" + Environment.NewLine);
46 | pathPasswordBatchHelper = ClassUtils.GetShortPathName(pathPasswordBatchHelper);
47 | }
48 | ClassUtils.AddEnvar("GIT_ASKPASS", pathPasswordBatchHelper);
49 |
50 | App.PrintLogMessage("Created HTTP password helper file: " + pathPasswordBatchHelper, MessageType.General);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ClassSSH.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Windows.Forms;
4 |
5 | namespace GitForce
6 | {
7 | ///
8 | /// Manage SSH access.
9 | /// This class should be instantiated on Linux OS only.
10 | ///
11 | public class ClassSSH
12 | {
13 | private readonly string pathHelper;
14 |
15 | ///
16 | /// Constructor class function, create batch file helper in the temp space
17 | ///
18 | public ClassSSH()
19 | {
20 | string pathHelpertLong = ClassUtils.WriteResourceToFile(Path.GetTempPath(), "git_ssh_helper.sh", Properties.Resources.git_ssh_helper);
21 | pathHelper = ClassUtils.GetShortPathName(pathHelpertLong);
22 | // Make the batch file executable: this trick will only work with Mono
23 | File.SetAttributes(pathHelper, (FileAttributes)((uint) File.GetAttributes (pathHelper) | 0x80000000));
24 | App.PrintLogMessage("SSH helper path:" + pathHelper, MessageType.Error);
25 | ClassUtils.AddEnvar("GIT_SSH", pathHelper);
26 | }
27 |
28 | ///
29 | /// Destructor for the class make sure the resources are properly disposed of
30 | ///
31 | ~ClassSSH()
32 | {
33 | // No real harm done if we fail to remove temp files. The next time GitForce is
34 | // run we will reuse the same files, so the temp folder will not grow.
35 | try
36 | {
37 | // Note: We leave these files in to allow secondary application instances to co-exist
38 | //File.Delete(pathHelper);
39 | }
40 | catch (Exception ex)
41 | {
42 | MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/ClassWin32.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace GitForce
6 | {
7 | ///
8 | /// Class containing NativeMethods interoperbility helper functions
9 | ///
10 | static class NativeMethods
11 | {
12 | public const int SB_BOTTOM = 0x0007;
13 | public const int WM_CLOSE = 0x0010;
14 | public const int WM_PAINT = 0x000F;
15 | public const int WM_VSCROLL = 0x0115;
16 | public const int HWND_BROADCAST = 0xffff;
17 | public const int WM_COMMAND = 0x0111;
18 | public const int TCM_ADJUSTRECT = 0x1328;
19 |
20 | public static readonly uint WmShowme = RegisterWindowMessage("WM_SHOWME");
21 |
22 | [DllImport("user32")]
23 | public static extern bool PostMessage(IntPtr hwnd, uint msg, IntPtr wparam, IntPtr lparam);
24 |
25 | [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
26 | static extern uint RegisterWindowMessage(string lpString);
27 |
28 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
29 | public static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
30 |
31 | [DllImport("user32.dll")]
32 | public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
33 |
34 | [DllImport("kernel32.dll")]
35 | static extern bool AttachConsole(int dwProcessId);
36 | private const int ATTACH_PARENT_PROCESS = -1;
37 |
38 | [DllImport("kernel32.dll")]
39 | public static extern bool FreeConsole();
40 |
41 | [DllImport("kernel32")]
42 | public static extern int GetShortPathName(string lpszLongPath, StringBuilder lpszShortPath,int bufSize);
43 |
44 | [DllImport("user32.dll")]
45 | public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
46 |
47 | ///
48 | /// Attaches a console so we can use Console class to print.
49 | /// This is needed only on Windows implementation where WinForms app detaches from its console.
50 | ///
51 | public static void AttachConsole()
52 | {
53 | AttachConsole(ATTACH_PARENT_PROCESS);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/ClassWinGeometry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Specialized;
4 | using System.Drawing;
5 | using System.Windows.Forms;
6 |
7 | namespace GitForce
8 | {
9 | ///
10 | /// Save and restore individual form's location and sizes
11 | ///
12 | static class ClassWinGeometry
13 | {
14 | private class Geometry
15 | {
16 | public Point Location;
17 | public Size Size;
18 | }
19 |
20 | #region Operations on a database
21 |
22 | ///
23 | /// Contains the lookup of geometry information for a particular form class
24 | ///
25 | private static readonly Dictionary wnd = new Dictionary();
26 |
27 | ///
28 | /// Loads geometry database from the program Settings.
29 | ///
30 | private static void LoadGeometryDatabase()
31 | {
32 | // Settings contains string collection of individual form information,
33 | // each piece of data is separated by space
34 | StringCollection db = Properties.Settings.Default.WindowsGeometries;
35 | foreach (var w in db)
36 | {
37 | string[] s = w.Split(' ');
38 | if (!string.IsNullOrEmpty(s[0]))
39 | {
40 | Geometry g = new Geometry
41 | {
42 | Location = new Point(int.Parse(s[1]), int.Parse(s[2])),
43 | Size = new Size(int.Parse(s[3]), int.Parse(s[4]))
44 | };
45 | wnd.Add(s[0], g);
46 | }
47 | }
48 | }
49 |
50 | ///
51 | /// Saves geometry database into the program Settings.
52 | ///
53 | public static void SaveGeometryDatabase()
54 | {
55 | StringCollection db = new StringCollection();
56 |
57 | // Settings contains string collection of individual form information,
58 | // each piece of data is separated by space
59 | foreach (var item in wnd)
60 | {
61 | Geometry g = item.Value;
62 | string s = String.Format("{0} {1} {2} {3} {4}",
63 | item.Key, g.Location.X, g.Location.Y, g.Size.Width, g.Size.Height);
64 | db.Add(s);
65 | }
66 | Properties.Settings.Default.WindowsGeometries = db;
67 | }
68 |
69 | #endregion
70 |
71 | #region Helper methods for dialog forms
72 |
73 | ///
74 | /// Restore form's location and size
75 | ///
76 | public static void Restore(Form form)
77 | {
78 | string name = form.GetType().Name;
79 | Geometry g;
80 |
81 | // If this is first invocation (hash is empty), load the window hash set
82 | if (wnd.Count == 0)
83 | LoadGeometryDatabase();
84 |
85 | // Find the form in our cache and assign its location and size
86 | if (wnd.TryGetValue(name, out g))
87 | {
88 | form.Location = g.Location;
89 | form.Size = g.Size;
90 | form.WindowState = FormWindowState.Normal;
91 | }
92 | else
93 | {
94 | // Form was not found in the database.
95 | // A good default is to center it around it's parent.
96 | form.StartPosition = FormStartPosition.CenterParent;
97 | }
98 | }
99 |
100 | ///
101 | /// Saves form's location and size
102 | ///
103 | public static void Save(Form form)
104 | {
105 | string name = form.GetType().Name;
106 |
107 | // Only save geometry if the form state is normal (not maximized or minimized)
108 | if (form.WindowState == FormWindowState.Normal)
109 | {
110 | // Simply update our cache
111 | Geometry g = new Geometry {Location = form.Location, Size = form.Size};
112 | if (wnd.ContainsKey(name))
113 | wnd[name] = g;
114 | else
115 | wnd.Add(name, g);
116 | }
117 | }
118 |
119 | #endregion
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/FormAbout.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace GitForce
5 | {
6 | public partial class FormAbout : Form
7 | {
8 | public FormAbout()
9 | {
10 | InitializeComponent();
11 | ClassWinGeometry.Restore(this);
12 |
13 | // Add the version number and the build date from the assembly info file
14 | labelVersion.Text = "Version " + ClassVersion.GetVersion();
15 | labelBuild.Text = ClassVersion.GetBuild();
16 |
17 | // If there is a new version available, show the label and a button
18 | labelNewVersionAvailable.Visible = btDownload.Visible = App.Version.NewVersionAvailable;
19 |
20 | textLic.Text =
21 | "THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR " +
22 | "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY," +
23 | "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE " +
24 | "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER " +
25 | "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, " +
26 | "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN " +
27 | "THE SOFTWARE.";
28 | }
29 |
30 | ///
31 | /// Form is closing.
32 | ///
33 | private void FormAboutFormClosing(object sender, FormClosingEventArgs e)
34 | {
35 | ClassWinGeometry.Save(this);
36 | }
37 |
38 | ///
39 | /// User clicked on a link to the GPL license
40 | ///
41 | private void LinkGplClicked(object sender, LinkLabelLinkClickedEventArgs e)
42 | {
43 | ClassHelp.Handler("GPL");
44 | }
45 |
46 | private void LinkBaltazarStudiosLinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
47 | {
48 | ClassHelp.Handler("BaltazarStudios");
49 | }
50 |
51 | ///
52 | /// User clicked on the "Copy Email" button
53 | /// Copy the email address to clipboard.
54 | ///
55 | private void BtCopyEmailClick(object sender, EventArgs e)
56 | {
57 | Clipboard.SetText("BaltazarStudios@gmail.com");
58 | }
59 |
60 | ///
61 | /// User clicked a button to download a new version
62 | ///
63 | private void DownloadClick(object sender, EventArgs e)
64 | {
65 | ClassHelp.Handler("Download");
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/FormChangelistFilter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace GitForce
5 | {
6 | public partial class FormChangelistFilter : Form
7 | {
8 | ///
9 | /// Final git log filter string
10 | ///
11 | public string gitFilter = "";
12 |
13 | ///
14 | /// Specifies only the SHA1 filter string
15 | ///
16 | public string filterSha => checkBoxSha.Checked ? textBoxSha.Text.Trim() : "";
17 |
18 | public FormChangelistFilter()
19 | {
20 | InitializeComponent();
21 | ClassWinGeometry.Restore(this);
22 |
23 | dateTimeBefore.Value = DateTime.Today;
24 | dateTimeAfter.Value = DateTime.Today;
25 | }
26 |
27 | ///
28 | /// Form is closing.
29 | ///
30 | private void FormChangelistFilterFormClosing(object sender, FormClosingEventArgs e)
31 | {
32 | ClassWinGeometry.Save(this);
33 | }
34 |
35 | ///
36 | /// User clicked on the OK button, format the git filter string
37 | ///
38 | private void BtOkClick(object sender, EventArgs e)
39 | {
40 | gitFilter = "";
41 |
42 | if (checkBoxMessage.Checked)
43 | gitFilter += " --grep=\"" + textBoxMessage.Text + "\"";
44 |
45 | if (checkBoxAuthor.Checked)
46 | gitFilter += " --author=\"" + textBoxAuthor.Text + "\"";
47 |
48 | if (checkBoxBefore.Checked)
49 | {
50 | DateTime dt = dateTimeBefore.Value;
51 | gitFilter += " --before=" + String.Format("{0:yyyy/MM/dd}", dt);
52 | }
53 |
54 | if (checkBoxAfter.Checked)
55 | {
56 | DateTime dt = dateTimeAfter.Value;
57 | gitFilter += " --after=" + String.Format("{0:yyyy/MM/dd}", dt);
58 | }
59 |
60 | App.PrintLogMessage("Condition: " + gitFilter, MessageType.General);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/FormCommitMerge.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using System.Linq;
4 | using System.Windows.Forms;
5 |
6 | namespace GitForce
7 | {
8 | ///
9 | /// This form is used for:
10 | /// 1. Commit - actually commit a full merge operation
11 | /// 2. Edit commit - edit an existing merge commit
12 | ///
13 | public partial class FormCommitMerge : Form
14 | {
15 | public FormCommitMerge(bool forCommit, string description)
16 | {
17 | InitializeComponent();
18 | ClassWinGeometry.Restore(this);
19 |
20 | textDescription.Font = Properties.Settings.Default.commitFont;
21 |
22 | // If we are updating the change, the function is slightly different.
23 | if (forCommit == false)
24 | btCommit.Text = "Update";
25 |
26 | textDescription.Text = description;
27 | textDescription.SelectAll();
28 | }
29 |
30 | ///
31 | /// Form is closing
32 | ///
33 | private void FormCommitMergeFormClosing(object sender, FormClosingEventArgs e)
34 | {
35 | ClassWinGeometry.Save(this);
36 | }
37 |
38 | ///
39 | /// On form load, set the focus to the text box.
40 | /// This is a way to have it start with all text selected.
41 | ///
42 | private void FormCommitMergeLoad(object sender, EventArgs e)
43 | {
44 | textDescription.Focus();
45 | }
46 |
47 | ///
48 | /// Set a list of files to appear in the files pane
49 | ///
50 | public void SetFiles(ClassCommit bundle)
51 | {
52 | listFiles.Items.AddRange(bundle.Files.ToArray());
53 | }
54 |
55 | ///
56 | /// Return the changelist description text
57 | ///
58 | public string GetDescription()
59 | {
60 | return textDescription.Text.Trim();
61 | }
62 |
63 | ///
64 | /// Capture commit description text change event in order to enable "Submit" button
65 | /// when the text is non-empty.
66 | /// The secondary purpose is to check the text wrapping margins.
67 | ///
68 | private void TextDescriptionTextChanged(object sender, EventArgs e)
69 | {
70 | btCommit.Enabled = textDescription.Text.Trim().Length > 0;
71 |
72 | string[] lines = textDescription.Text.Trim().Split((Environment.NewLine).ToCharArray()).ToArray();
73 | int w1 = lines[0].Length;
74 | int w2 = 0;
75 |
76 | // Check the rest of the lines (find the maximum)
77 | if (lines.Length > 1)
78 | for (int y = 1; y < lines.Length; y++)
79 | if (lines[y].Length > w2)
80 | w2 = lines[y].Length;
81 |
82 | labelWidth.Text = String.Format("Text span: First line {0}/{1}, body {2}/{3}",
83 | w1, Properties.Settings.Default.commitW1,
84 | w2, Properties.Settings.Default.commitW2);
85 |
86 | // Print the cursor location
87 | labelCursor.Text = string.Format("({0},{1})",
88 | textDescription.SelectionStart - textDescription.GetFirstCharIndexOfCurrentLine(),
89 | textDescription.GetLineFromCharIndex(textDescription.SelectionStart));
90 |
91 | // Color the text and the label in red if the span was reached))
92 | if (w1 > Properties.Settings.Default.commitW1 || w2 > Properties.Settings.Default.commitW2)
93 | textDescription.ForeColor = labelWidth.ForeColor = Color.Red;
94 | else
95 | textDescription.ForeColor = labelWidth.ForeColor = SystemColors.ControlText;
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/FormCustomToolArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace GitForce
5 | {
6 | ///
7 | /// Form to ask user for arguments before running a custom tool.
8 | ///
9 | public partial class FormCustomToolArgs : Form
10 | {
11 | ///
12 | /// Constructor that takes:
13 | /// form title string (used to display description of the query)
14 | /// initial argument string
15 | /// flag whether to show or now Browse... button
16 | ///
17 | public FormCustomToolArgs(string desc, string args, bool isBrowse)
18 | {
19 | InitializeComponent();
20 | ClassWinGeometry.Restore(this);
21 |
22 | Text = desc;
23 | btBrowse.Visible = isBrowse;
24 | comboArgs.Text = args;
25 | }
26 |
27 | ///
28 | /// Access a virtual member
29 | ///
30 | public override sealed string Text
31 | {
32 | get { return base.Text; }
33 | set { base.Text = value; }
34 | }
35 |
36 | ///
37 | /// Form is closing.
38 | ///
39 | private void FormCustomToolArgsFormClosing(object sender, FormClosingEventArgs e)
40 | {
41 | ClassWinGeometry.Save(this);
42 | }
43 |
44 | ///
45 | /// Return the final argument string
46 | ///
47 | public string GetArgs()
48 | {
49 | return comboArgs.Text;
50 | }
51 |
52 | ///
53 | /// Add a user-selected file to the arguments
54 | ///
55 | private void BtBrowseClick(object sender, EventArgs e)
56 | {
57 | if (openFile.ShowDialog() == DialogResult.OK)
58 | {
59 | comboArgs.Text += openFile.FileName;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/FormDeleteRepo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Windows.Forms;
4 |
5 | namespace GitForce
6 | {
7 | public partial class FormDeleteRepo : Form
8 | {
9 | ///
10 | /// Radio button selection mode
11 | ///
12 | private int radioSelection;
13 |
14 | ///
15 | /// Root directory to delete from
16 | ///
17 | private readonly string dir;
18 |
19 | public FormDeleteRepo(string root)
20 | {
21 | InitializeComponent();
22 | ClassWinGeometry.Restore(this);
23 |
24 | dir = textPath.Text = root;
25 | }
26 |
27 | ///
28 | /// Form is closing.
29 | ///
30 | private void FormDeleteRepoFormClosing(object sender, FormClosingEventArgs e)
31 | {
32 | ClassWinGeometry.Save(this);
33 | }
34 |
35 | ///
36 | /// Remove directories and files if selected
37 | ///
38 | private void BtDeleteClick(object sender, EventArgs e)
39 | {
40 | // Move CWD away as it prevents Windows OS to cleanly delete directory
41 | Directory.SetCurrentDirectory(App.AppHome);
42 |
43 | bool ret = true;
44 | // Depending on the selection, do the deletion:
45 | // 0: dont delete anythng
46 | // 1: delete only working files
47 | // 2: delete only .git tree
48 | // 3: delete complete repo folder
49 |
50 | if (radioSelection == 1)
51 | {
52 | DirectoryInfo dirInfo = new DirectoryInfo(dir);
53 | ret = ClassUtils.DeleteFolder(dirInfo, true, true); // Preserve .git, preserve root folder
54 | }
55 |
56 | if (radioSelection == 2)
57 | {
58 | DirectoryInfo dirInfo = new DirectoryInfo(dir + Path.DirectorySeparatorChar + ".git");
59 | ret = ClassUtils.DeleteFolder(dirInfo, false, false); // Remove .git, remove root folder (.git)
60 | }
61 |
62 | if (radioSelection == 3)
63 | {
64 | DirectoryInfo dirInfo = new DirectoryInfo(dir);
65 | ret = ClassUtils.DeleteFolder(dirInfo, false, false); // Remove .git, remove root folder
66 | }
67 |
68 | if (ret == false)
69 | MessageBox.Show("Some files could not be removed!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
70 | }
71 |
72 | ///
73 | /// Any one of the 3 radio buttons are clicked. Store the selection.
74 | ///
75 | private void RadioButtonClicked(object sender, EventArgs e)
76 | {
77 | radioSelection = int.Parse((sender as RadioButton).Tag.ToString());
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/FormDiffMissing.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Windows.Forms;
5 |
6 | namespace GitForce
7 | {
8 | public partial class FormDiffMissing : Form
9 | {
10 | public FormDiffMissing()
11 | {
12 | InitializeComponent();
13 |
14 | if (!ClassUtils.IsMono())
15 | {
16 | // Disabling the auto-download of KDiff3 for now until I figure out
17 | // how to pick up a file from that SF site...
18 | //
19 | // labelInfo.Text += "If you prefer, I can download and install KDiff3 for you.";
20 | // btInstall.Visible = true;
21 | }
22 | }
23 |
24 | ///
25 | /// User clicked on a link to a diff utility, open it up in a web browser.
26 | ///
27 | private void LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
28 | {
29 | ClassUtils.OpenWebLink((sender as LinkLabel).Tag.ToString());
30 | }
31 |
32 | ///
33 | /// User clicked on a Install KDiff3 button to download and install KDiff3
34 | /// (Windows only)
35 | ///
36 | /// *** This button was removed ***
37 | /// I left this code in place should it be needed.
38 | /// The button was downloading this specific executable and installing it.
39 | /// However, github does not provide easy file access. There are ways around
40 | /// it and perhaps it is worth redoing it. One day.
41 | ///
42 | ///
43 | private void BtInstallClick(object sender, EventArgs e)
44 | {
45 | string installerFile = Path.GetTempFileName(); // Junk name so we can safely call 'Delete'
46 | try
47 | {
48 | FormDownload formDownload = new FormDownload("Download KDiff3",
49 | @"https://sourceforge.net/projects/kdiff3/files/kdiff3/0.9.98",
50 | @">(?\S+.exe)", "/download/");
51 |
52 | // If the download succeeded, run the installer file
53 | if (formDownload.ShowDialog() == DialogResult.OK)
54 | {
55 | // Run the installer application that we just downloaded and wait for it to finish
56 | installerFile = formDownload.TargetFile;
57 | Process procInstaller = Process.Start(installerFile);
58 | procInstaller.WaitForExit();
59 |
60 | if (procInstaller.ExitCode == 0)
61 | DialogResult = DialogResult.OK;
62 | }
63 | }
64 | catch (Exception ex)
65 | {
66 | MessageBox.Show(ex.Message, "Error");
67 | }
68 | finally
69 | {
70 | // Make sure we don't leave temporary files around
71 | File.Delete(installerFile);
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/FormHttpsAuth.cs:
--------------------------------------------------------------------------------
1 | using System.Text.RegularExpressions;
2 | using System.Windows.Forms;
3 |
4 | namespace GitForce
5 | {
6 | public partial class FormHttpsAuth : Form
7 | {
8 | ///
9 | /// Keep user name and password fields as typed in the control
10 | ///
11 | public string Username
12 | {
13 | set { textUsername.Text = value.Trim(); }
14 | get { return textUsername.Text.Trim(); }
15 | }
16 | public string Password
17 | {
18 | set { textPassword.Text = value.Trim(); }
19 | get { return textPassword.Text.Trim(); }
20 | }
21 |
22 | ///
23 | /// Form constructor
24 | ///
25 | public FormHttpsAuth(bool enableUsername)
26 | {
27 | InitializeComponent();
28 | ClassWinGeometry.Restore(this);
29 |
30 | textUsername.Enabled = enableUsername;
31 | }
32 |
33 | ///
34 | /// Form is closing
35 | ///
36 | private void FormHttpsAuth_FormClosing(object sender, FormClosingEventArgs e)
37 | {
38 | ClassWinGeometry.Save(this);
39 | }
40 |
41 | ///
42 | /// Show or hide password field
43 | ///
44 | private void CheckShowCheckedChanged(object sender, System.EventArgs e)
45 | {
46 | textPassword.UseSystemPasswordChar = !checkReveal.Checked;
47 | }
48 |
49 | ///
50 | /// Enables or disables OK button based on validity of the user name and password fields
51 | ///
52 | private void ValidateOk(object sender, System.EventArgs e)
53 | {
54 | // Validator for the user name field: must start with a letter and ...
55 | string username = textUsername.Text.Trim();
56 | Regex r = new Regex("^[a-zA-Z][a-zA-Z0-9_]*$");
57 |
58 | // This is a really lame validator for the password field
59 | // We simply want to avoid some 'dangerous' characters, including spaces
60 | string password = textPassword.Text.Trim();
61 |
62 | btOK.Enabled = (!textUsername.Enabled || r.IsMatch(username)) && (password.Length > 0) && password.IndexOfAny(@" \/".ToCharArray()) == -1;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/FormLog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Windows.Forms;
5 |
6 | namespace GitForce
7 | {
8 | ///
9 | /// Implements the Log form.
10 | /// This form is never closed but is only shown or hidden as requested.
11 | ///
12 | public partial class FormLog : Form
13 | {
14 | public FormLog()
15 | {
16 | InitializeComponent();
17 | ClassWinGeometry.Restore(this);
18 |
19 | // Add our main print function callback delegate
20 | App.PrintLogMessage += Print;
21 |
22 | if (App.AppLog != null)
23 | Print("Logging: " + App.AppLog, MessageType.General);
24 |
25 | // Prints only in Debug build...
26 | Debug("Debug build.");
27 | }
28 |
29 | ///
30 | /// Form is closing.
31 | ///
32 | private void FormLogFormClosing(object sender, FormClosingEventArgs e)
33 | {
34 | ClassWinGeometry.Save(this);
35 |
36 | // Remove our print function delegate
37 | App.PrintLogMessage -= Print;
38 | }
39 |
40 | ///
41 | /// Form helper function that shows or hides a form
42 | ///
43 | public void ShowWindow(bool toShow)
44 | {
45 | if (!Visible && toShow)
46 | Show();
47 |
48 | if (Visible && !toShow)
49 | Hide();
50 | }
51 |
52 | ///
53 | /// Adds a text string to the end of the text box.
54 | /// For performance reasons, only up to 120 characters of text are added in one call.
55 | /// This is a thread-safe call.
56 | ///
57 | private void Print(string text, MessageType type)
58 | {
59 | if (textBox.InvokeRequired)
60 | textBox.BeginInvoke((MethodInvoker)(() => Print(text, type)));
61 | else
62 | {
63 | try
64 | {
65 | // Mirror the text to the file log, if enabled
66 | if (App.AppLog != null)
67 | using (StreamWriter sw = File.AppendText(App.AppLog))
68 | sw.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "|" + text);
69 |
70 | // Print the text into the textbox
71 | int len = Math.Min(text.Length, 120);
72 | textBox.Text += text.Substring(0, len).Trim() + Environment.NewLine;
73 |
74 | // Scroll to the bottom and move carret position
75 | textBox.SelectionStart = textBox.TextLength;
76 | textBox.ScrollToCaret();
77 | }
78 | catch (Exception ex)
79 | {
80 | MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
81 | }
82 | }
83 | }
84 |
85 | ///
86 | /// Prints a message only in debug build
87 | /// This is a thread-safe call.
88 | ///
89 | [Conditional("DEBUG")]
90 | private void Debug(string text)
91 | {
92 | Print(text, MessageType.Debug);
93 | }
94 |
95 | #region Context menu handlers: Copy, Select All and Clear
96 |
97 | private void CopyToolStripMenuItemClick(object sender, EventArgs e)
98 | {
99 | textBox.Copy();
100 | }
101 |
102 | private void SelectAllToolStripMenuItemClick(object sender, EventArgs e)
103 | {
104 | textBox.SelectAll();
105 | }
106 |
107 | private void ClearToolStripMenuItemClick(object sender, EventArgs e)
108 | {
109 | textBox.Clear();
110 | }
111 |
112 | #endregion
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/FormMergeBranch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace GitForce
5 | {
6 | ///
7 | /// Form to merge a branch.
8 | ///
9 | public partial class FormMergeBranch : Form
10 | {
11 | public FormMergeBranch()
12 | {
13 | InitializeComponent();
14 | ClassWinGeometry.Restore(this);
15 |
16 | ClassBranches branches = App.Repos.Current.Branches;
17 |
18 | labelCurrentBranchName.Text = "Current branch is \"" + branches.Current + "\"";
19 |
20 | // Add all available branches to the list of branches to merge
21 | foreach (var branch in branches.Local)
22 | listBranches.Items.Add(branch);
23 |
24 | foreach (var branch in branches.Remote)
25 | listBranches.Items.Add(branch);
26 |
27 | listBranches.Items.RemoveAt(listBranches.Items.IndexOf(branches.Current));
28 |
29 | if (listBranches.Items.Count > 0)
30 | {
31 | listBranches.SelectedIndex = 0;
32 | btMerge.Enabled = true;
33 | }
34 | }
35 |
36 | ///
37 | /// Form is closing.
38 | ///
39 | private void FormMergeBranchFormClosing(object sender, FormClosingEventArgs e)
40 | {
41 | ClassWinGeometry.Save(this);
42 | }
43 |
44 | ///
45 | /// Button is clicked to perform a branch merge.
46 | ///
47 | private void BtMergeClick(object sender, EventArgs e)
48 | {
49 | string cmd = "merge " + listBranches.SelectedItem;
50 |
51 | App.Repos.Current.RunCmd(cmd);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/FormMergeMissing.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace GitForce
4 | {
5 | public partial class FormMergeMissing : Form
6 | {
7 | public FormMergeMissing()
8 | {
9 | InitializeComponent();
10 | }
11 |
12 | ///
13 | /// User clicked on a link to a merge utility, open it up in a web browser.
14 | ///
15 | private void LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
16 | {
17 | ClassUtils.OpenWebLink((sender as LinkLabel).Tag.ToString());
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/FormNewRepoScan.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Windows.Forms;
6 |
7 | namespace GitForce
8 | {
9 | ///
10 | /// Scan for new repositories
11 | ///
12 | public partial class FormNewRepoScan : Form
13 | {
14 | public FormNewRepoScan()
15 | {
16 | InitializeComponent();
17 | ClassWinGeometry.Restore(this);
18 |
19 | checkBoxDeepScan.Checked = Properties.Settings.Default.RepoDeepScan;
20 | }
21 |
22 | private void FormNewRepoScanFormClosing(object sender, FormClosingEventArgs e)
23 | {
24 | ClassWinGeometry.Save(this);
25 | }
26 |
27 | ///
28 | /// Return a list of selected directories
29 | ///
30 | public List GetList()
31 | {
32 | return listRepos.Items.Cast