├── .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(). 33 | Where((t, i) => listRepos.GetItemCheckState(i) == CheckState.Checked). 34 | Select(t => t.ToString()).ToList(); 35 | } 36 | 37 | /// 38 | /// Browse for a initial directory to scan from 39 | /// 40 | private void BtBrowseClick(object sender, EventArgs e) 41 | { 42 | if (folderDlg.ShowDialog() == DialogResult.OK) 43 | { 44 | textRoot.Text = folderDlg.SelectedPath; 45 | } 46 | } 47 | 48 | /// 49 | /// Start scanning 50 | /// 51 | private void BtScanClick(object sender, EventArgs e) 52 | { 53 | FormNewRepoScanProgress formScanProgress = new FormNewRepoScanProgress(textRoot.Text, checkBoxDeepScan.Checked); 54 | if (formScanProgress.ShowDialog() == DialogResult.OK) 55 | { 56 | // Add only unique values to the list, so we can run the scan on multiple 57 | // directories and add all scanned paths, even if they have common folders 58 | foreach (var path in formScanProgress.Gits.ToArray(). 59 | Where(path => !listRepos.Items.Contains(path))) 60 | listRepos.Items.Add(path); 61 | btSelectAll.Enabled = btSelectNone.Enabled = listRepos.Items.Count > 0; 62 | BtSelectAllClick(null, null); 63 | } 64 | } 65 | 66 | /// 67 | /// Select all directories 68 | /// 69 | private void BtSelectAllClick(object sender, EventArgs e) 70 | { 71 | for (int i = 0; i < listRepos.Items.Count; i++) 72 | listRepos.SetItemChecked(i, true); 73 | } 74 | 75 | /// 76 | /// Select no directory from the list 77 | /// 78 | private void BtSelectNoneClick(object sender, EventArgs e) 79 | { 80 | for (int i = 0; i < listRepos.Items.Count; i++) 81 | listRepos.SetItemChecked(i, false); 82 | } 83 | 84 | /// 85 | /// On text in the root directory changed, verify the directory and enable Scan button 86 | /// 87 | private void TextRootTextChanged(object sender, EventArgs e) 88 | { 89 | btScan.Enabled = Path.IsPathRooted(textRoot.Text) && Directory.Exists(textRoot.Text); 90 | } 91 | 92 | /// 93 | /// Item in the list of paths is being checked, adjust button enables. 94 | /// 95 | private void ListReposItemCheck(object sender, ItemCheckEventArgs e) 96 | { 97 | if (e.NewValue == CheckState.Checked) 98 | btAdd.Enabled = true; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /FormNewRepoScanAdd.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce 2 | { 3 | partial class FormNewRepoScanAdd 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btCancel = new System.Windows.Forms.Button(); 32 | this.textRepo = new System.Windows.Forms.TextBox(); 33 | this.progressBar = new System.Windows.Forms.ProgressBar(); 34 | this.SuspendLayout(); 35 | // 36 | // btCancel 37 | // 38 | this.btCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 39 | this.btCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 40 | this.btCancel.Location = new System.Drawing.Point(283, 39); 41 | this.btCancel.Name = "btCancel"; 42 | this.btCancel.Size = new System.Drawing.Size(75, 23); 43 | this.btCancel.TabIndex = 0; 44 | this.btCancel.Text = "Cancel"; 45 | this.btCancel.UseVisualStyleBackColor = true; 46 | this.btCancel.Click += new System.EventHandler(this.BtCancelClick); 47 | // 48 | // textRepo 49 | // 50 | this.textRepo.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 51 | | System.Windows.Forms.AnchorStyles.Right))); 52 | this.textRepo.Enabled = false; 53 | this.textRepo.Location = new System.Drawing.Point(12, 12); 54 | this.textRepo.Name = "textRepo"; 55 | this.textRepo.Size = new System.Drawing.Size(346, 20); 56 | this.textRepo.TabIndex = 1; 57 | // 58 | // progressBar 59 | // 60 | this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 61 | | System.Windows.Forms.AnchorStyles.Right))); 62 | this.progressBar.Location = new System.Drawing.Point(13, 39); 63 | this.progressBar.Name = "progressBar"; 64 | this.progressBar.Size = new System.Drawing.Size(264, 23); 65 | this.progressBar.TabIndex = 2; 66 | // 67 | // FormNewRepoScanAdd 68 | // 69 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 70 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 71 | this.ClientSize = new System.Drawing.Size(370, 74); 72 | this.Controls.Add(this.progressBar); 73 | this.Controls.Add(this.textRepo); 74 | this.Controls.Add(this.btCancel); 75 | this.MaximizeBox = false; 76 | this.MinimizeBox = false; 77 | this.MinimumSize = new System.Drawing.Size(180, 112); 78 | this.Name = "FormNewRepoScanAdd"; 79 | this.ShowIcon = false; 80 | this.ShowInTaskbar = false; 81 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 82 | this.Text = "Adding Repositories..."; 83 | this.Shown += new System.EventHandler(this.FormNewRepoScanAddShown); 84 | this.ResumeLayout(false); 85 | this.PerformLayout(); 86 | 87 | } 88 | 89 | #endregion 90 | 91 | private System.Windows.Forms.Button btCancel; 92 | private System.Windows.Forms.TextBox textRepo; 93 | private System.Windows.Forms.ProgressBar progressBar; 94 | } 95 | } -------------------------------------------------------------------------------- /FormNewRepoScanAdd.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.IO; 5 | using System.Threading; 6 | using System.Windows.Forms; 7 | 8 | namespace GitForce 9 | { 10 | /// 11 | /// Add a set of repositories to the workspace 12 | /// 13 | public partial class FormNewRepoScanAdd : Form 14 | { 15 | private readonly List dirs; 16 | private bool enableAdd; 17 | 18 | public FormNewRepoScanAdd(List dirList) 19 | { 20 | InitializeComponent(); 21 | dirs = dirList; 22 | 23 | // If there are 5 repos or more, display the progress bar 24 | progressBar.Visible = dirs.Count() >= 5; 25 | progressBar.Maximum = dirs.Count(); 26 | progressBar.Value = 0; 27 | } 28 | 29 | /// 30 | /// Start scanning at the time the form is first shown 31 | /// 32 | private void FormNewRepoScanAddShown(object sender, EventArgs e) 33 | { 34 | enableAdd = true; 35 | int count = 1; 36 | 37 | // Create each of the repos for the selected directories 38 | foreach (var d in dirs) 39 | { 40 | if (enableAdd == false) 41 | return; 42 | try 43 | { 44 | // Update progress bar and make sure it gets painted 45 | progressBar.Value = count++; 46 | Thread.Sleep(1); 47 | 48 | textRepo.Text = d; 49 | Application.DoEvents(); 50 | Directory.SetCurrentDirectory(d); 51 | if (ClassGit.Run("init").Success() == false) 52 | throw new ClassException("init failed."); 53 | App.Repos.Add(d); 54 | } 55 | catch (Exception ex) 56 | { 57 | App.PrintLogMessage("Unable to add repo: " + ex.Message, MessageType.Error); 58 | App.PrintStatusMessage(ex.Message, MessageType.Error); 59 | } 60 | } 61 | DialogResult = DialogResult.OK; 62 | } 63 | 64 | /// 65 | /// Cancel adding repos 66 | /// 67 | private void BtCancelClick(object sender, EventArgs e) 68 | { 69 | enableAdd = false; 70 | DialogResult = DialogResult.OK; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /FormNewRepoScanProgress.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce 2 | { 3 | partial class FormNewRepoScanProgress 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btStop = new System.Windows.Forms.Button(); 32 | this.textDir = new System.Windows.Forms.TextBox(); 33 | this.SuspendLayout(); 34 | // 35 | // btStop 36 | // 37 | this.btStop.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 38 | this.btStop.DialogResult = System.Windows.Forms.DialogResult.Cancel; 39 | this.btStop.Location = new System.Drawing.Point(283, 39); 40 | this.btStop.Name = "btStop"; 41 | this.btStop.Size = new System.Drawing.Size(75, 23); 42 | this.btStop.TabIndex = 0; 43 | this.btStop.Text = "Stop"; 44 | this.btStop.UseVisualStyleBackColor = true; 45 | this.btStop.Click += new System.EventHandler(this.BtStopClick); 46 | // 47 | // textDir 48 | // 49 | this.textDir.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 50 | | System.Windows.Forms.AnchorStyles.Right))); 51 | this.textDir.Enabled = false; 52 | this.textDir.Location = new System.Drawing.Point(12, 12); 53 | this.textDir.Name = "textDir"; 54 | this.textDir.Size = new System.Drawing.Size(346, 20); 55 | this.textDir.TabIndex = 1; 56 | // 57 | // FormNewRepoScanProgress 58 | // 59 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 60 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 61 | this.ClientSize = new System.Drawing.Size(370, 74); 62 | this.Controls.Add(this.textDir); 63 | this.Controls.Add(this.btStop); 64 | this.MaximizeBox = false; 65 | this.MinimizeBox = false; 66 | this.MinimumSize = new System.Drawing.Size(180, 112); 67 | this.Name = "FormNewRepoScanProgress"; 68 | this.ShowIcon = false; 69 | this.ShowInTaskbar = false; 70 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 71 | this.Text = "Scanning..."; 72 | this.Shown += new System.EventHandler(this.FormNewRepoScanProgressShown); 73 | this.ResumeLayout(false); 74 | this.PerformLayout(); 75 | 76 | } 77 | 78 | #endregion 79 | 80 | private System.Windows.Forms.Button btStop; 81 | private System.Windows.Forms.TextBox textDir; 82 | } 83 | } -------------------------------------------------------------------------------- /FormNewRepoScanProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | 6 | namespace GitForce 7 | { 8 | /// 9 | /// Scan for the list of directories that potentially host Git repositories 10 | /// 11 | public partial class FormNewRepoScanProgress : Form 12 | { 13 | /// 14 | /// List of potential candidates to contain a git repository 15 | /// 16 | public readonly List Gits = new List(); 17 | 18 | private readonly string dir; 19 | private readonly bool deepScan; 20 | private bool enableScan; 21 | 22 | public FormNewRepoScanProgress(string directory, bool fDeepScan) 23 | { 24 | InitializeComponent(); 25 | dir = directory; 26 | deepScan = fDeepScan; 27 | } 28 | 29 | /// 30 | /// Recursively search folders starting at the given directory and 31 | /// add all paths that end with .git to the list of potential candidates 32 | /// 33 | private void SearchGit(string dir) 34 | { 35 | // Silently ignore unreachable directories 36 | try 37 | { 38 | foreach (var d in Directory.GetDirectories(dir)) 39 | { 40 | textDir.Text = d; 41 | Application.DoEvents(); 42 | if (enableScan == false) 43 | return; 44 | 45 | if (d.EndsWith(Path.DirectorySeparatorChar + ".git")) 46 | { 47 | Gits.Add(d.Substring(0, d.Length - 5)); 48 | if (deepScan == false) 49 | break; 50 | } 51 | else 52 | SearchGit(d); 53 | } 54 | } 55 | catch (Exception) {} 56 | } 57 | 58 | /// 59 | /// Start scanning at the time the form is first shown 60 | /// 61 | private void FormNewRepoScanProgressShown(object sender, EventArgs e) 62 | { 63 | Gits.Clear(); 64 | enableScan = true; 65 | try 66 | { 67 | SearchGit(dir); 68 | } 69 | catch (Exception ex) 70 | { 71 | MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 72 | enableScan = false; 73 | } 74 | DialogResult = DialogResult.OK; 75 | Close(); 76 | } 77 | 78 | /// 79 | /// Stop scanning and exit the dialog 80 | /// 81 | private void BtStopClick(object sender, EventArgs e) 82 | { 83 | enableScan = false; 84 | Application.DoEvents(); 85 | DialogResult = DialogResult.OK; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /FormNewRepoStep1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce 5 | { 6 | public partial class FormNewRepoStep1 : Form 7 | { 8 | /// 9 | /// Describes source for a new repo: "empty", "local" or "remote" 10 | /// 11 | public string Type { get { return type; } 12 | set { type = value; 13 | if (type.Equals("empty")) rbEmpty.Checked = true; 14 | if (type.Equals("local")) rbLocal.Checked = true; 15 | if (type.Equals("remote")) rbRemote.Checked = true; 16 | }} 17 | private string type; 18 | 19 | /// 20 | /// Path to a local git repo 21 | /// 22 | public string Local { 23 | get { return textBoxLocal.Text.Trim(); } 24 | set { textBoxLocal.Text = value; } 25 | } 26 | 27 | /// 28 | /// ClassRemote structure of a new repo 29 | /// 30 | public ClassRemotes.Remote Remote; 31 | 32 | /// 33 | /// Call this method to properly set the remote structure that is going to be used by this dialog 34 | /// 35 | public void SetRemote(ClassRemotes.Remote remote) 36 | { 37 | Remote = remote; 38 | remoteEdit.Set(Remote); 39 | } 40 | 41 | public FormNewRepoStep1() 42 | { 43 | InitializeComponent(); 44 | ClassWinGeometry.Restore(this); 45 | 46 | Type = "empty"; 47 | Local = String.Empty; 48 | 49 | // Set the default remote name 50 | Remote.Name = "origin"; 51 | Remote.PushCmd = ""; 52 | remoteEdit.Set(Remote); 53 | remoteEdit.AnyTextChanged += SomeTextChanged; 54 | } 55 | 56 | /// 57 | /// Form is closing. 58 | /// 59 | private void FormNewRepoStep1FormClosing(object sender, FormClosingEventArgs e) 60 | { 61 | ClassWinGeometry.Save(this); 62 | } 63 | 64 | /// 65 | /// Browse for the local path to directory to clone 66 | /// 67 | private void BtBrowseClick(object sender, EventArgs e) 68 | { 69 | folder.Description = @"Select a folder containing the root of a repository to clone:"; 70 | if (folder.ShowDialog() == DialogResult.OK) 71 | Local = folder.SelectedPath; 72 | } 73 | 74 | /// 75 | /// User changed the radio button source for the repo 76 | /// 77 | private void RbSourceCheckedChanged(object sender, EventArgs e) 78 | { 79 | RadioButton rb = sender as RadioButton; 80 | if (rb.Checked) 81 | { 82 | textBoxLocal.ReadOnly = true; 83 | btNext.Enabled = btBrowse.Enabled = remoteEdit.Enabled = false; 84 | remoteEdit.Enable(false, false); 85 | 86 | switch (Type = rb.Tag.ToString()) 87 | { 88 | case "empty": 89 | btNext.Enabled = true; 90 | break; 91 | case "local": 92 | textBoxLocal.ReadOnly = false; 93 | btBrowse.Enabled = true; 94 | btNext.Enabled = ClassUtils.DirStat(Local) == ClassUtils.DirStatType.Git; 95 | break; 96 | case "remote": 97 | remoteEdit.Enabled = true; 98 | remoteEdit.Enable(true, true); 99 | btNext.Enabled = remoteEdit.IsValid(); 100 | break; 101 | } 102 | } 103 | } 104 | 105 | /// 106 | /// Text in the local directory path changed. Validate the entry. 107 | /// 108 | private void TextBoxLocalTextChanged(object sender, EventArgs e) 109 | { 110 | btNext.Enabled = ClassUtils.DirStat(Local) == ClassUtils.DirStatType.Git; 111 | } 112 | 113 | /// 114 | /// Callback function called when text in the remote repo editing has changed. 115 | /// 116 | private void SomeTextChanged(bool valid) 117 | { 118 | btNext.Enabled = valid; 119 | Remote = remoteEdit.Get(); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /FormNewRepoStep2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | 5 | namespace GitForce 6 | { 7 | public partial class FormNewRepoStep2 : Form 8 | { 9 | /// 10 | /// Destination directory to create a new repo 11 | /// 12 | public string Destination 13 | { 14 | get { return ClassUtils.GetCombinedPath(textBoxRepoPath.Text.Trim(), textBoxProjectName.Text.Trim()); } 15 | set { textBoxRepoPath.Text = value; } 16 | } 17 | 18 | /// 19 | /// Project name 20 | /// 21 | public string ProjectName 22 | { 23 | get { return textBoxProjectName.Text.Trim(); } 24 | set { textBoxProjectName.Text = value; } 25 | } 26 | 27 | public string InitBranchName 28 | { 29 | get { return textBoxInitBranchName.Text.Trim(); } 30 | set { textBoxInitBranchName.Text = value; } 31 | } 32 | 33 | /// 34 | /// Optional extra parameters which can be set by the user 35 | /// 36 | public string Extra 37 | { 38 | get { return textBoxExtraArgs.Text.Trim(); } 39 | } 40 | 41 | public bool IsBare; 42 | public bool CheckTargetDirEmpty; 43 | 44 | public FormNewRepoStep2() 45 | { 46 | InitializeComponent(); 47 | ClassWinGeometry.Restore(this); 48 | } 49 | 50 | /// 51 | /// Form is closing. 52 | /// 53 | private void FormNewRepoStep2FormClosing(object sender, FormClosingEventArgs e) 54 | { 55 | ClassWinGeometry.Save(this); 56 | } 57 | 58 | /// 59 | /// Browse for the final path to the directory to init 60 | /// 61 | private void BtBrowseClick(object sender, EventArgs e) 62 | { 63 | folder.Description = @"Select a folder to host the new repository:"; 64 | if (folder.ShowDialog() == DialogResult.OK) 65 | textBoxRepoPath.Text = folder.SelectedPath; 66 | } 67 | 68 | /// 69 | /// Text changed in the destination path, validate it. 70 | /// 71 | private void TextBoxRepoPathTextChanged(object sender, EventArgs e) 72 | { 73 | // Target folder needs to be a valid directory, with or without files in it 74 | ClassUtils.DirStatType type = ClassUtils.DirStat(textBoxRepoPath.Text); 75 | btOK.Enabled = type == ClassUtils.DirStatType.Empty || type == ClassUtils.DirStatType.Nongit; 76 | // Additional checks for clone operations (where CheckTargetDirEmpty is true) 77 | if (CheckTargetDirEmpty) 78 | { 79 | // If the project name is specified, that complete path should not exist 80 | if (textBoxProjectName.Text.Trim().Length > 0) 81 | btOK.Enabled &= ClassUtils.DirStat(Destination) == ClassUtils.DirStatType.Invalid; 82 | } 83 | } 84 | 85 | /// 86 | /// Copy the bare checked state into a public variable that is exposed 87 | /// 88 | private void CheckBoxBareCheckedChanged(object sender, EventArgs e) 89 | { 90 | IsBare = checkBoxBare.Checked; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /FormPathToGit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | 5 | namespace GitForce 6 | { 7 | public partial class FormPathToGit : Form 8 | { 9 | /// 10 | /// Default path is the user's program files 11 | /// 12 | public string PathToGit; 13 | 14 | public FormPathToGit(string programFiles, string suggestPathToGit) 15 | { 16 | InitializeComponent(); 17 | 18 | textBoxPath.Text = programFiles; 19 | 20 | labelInfo.Text = "GitForce is a GUI front-end to the command line git. " + 21 | "That means you have to have git already installed. You can download git for Windows from the link below."; 22 | } 23 | 24 | /// 25 | /// Lets the user browse to a directory containing git. 26 | /// 27 | private void BtBrowseClick(object sender, EventArgs e) 28 | { 29 | OpenFileDialog fileDlg = new OpenFileDialog(); 30 | fileDlg.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); 31 | if (fileDlg.ShowDialog() == DialogResult.OK) 32 | { 33 | textBoxPath.Text = fileDlg.FileName; 34 | } 35 | } 36 | 37 | /// 38 | /// Open the web browser with a link to Git for Windows 39 | /// 40 | private void GitLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 41 | { 42 | ClassUtils.OpenWebLink(linkLabel.Tag.ToString()); 43 | } 44 | 45 | /// 46 | /// As the text in the git path is changing, check for the git executable name 47 | /// and enable or disable the OK button based on this check 48 | /// 49 | private void TextBoxPathTextChanged(object sender, EventArgs e) 50 | { 51 | PathToGit = textBoxPath.Text; 52 | btOK.Enabled = File.Exists(PathToGit) && PathToGit.EndsWith("git.exe"); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /FormRemoteAddEdit.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce 2 | { 3 | partial class FormRemoteAddEdit 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.remoteEdit = new RemoteEdit(); 32 | this.btOK = new System.Windows.Forms.Button(); 33 | this.btCancel = new System.Windows.Forms.Button(); 34 | this.SuspendLayout(); 35 | // 36 | // RemoteEdit 37 | // 38 | this.remoteEdit.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 39 | | System.Windows.Forms.AnchorStyles.Right))); 40 | this.remoteEdit.Location = new System.Drawing.Point(12, 12); 41 | this.remoteEdit.MinimumSize = new System.Drawing.Size(346, 146); 42 | this.remoteEdit.Name = "remoteEdit"; 43 | this.remoteEdit.Size = new System.Drawing.Size(422, 146); 44 | this.remoteEdit.TabIndex = 0; 45 | // 46 | // btOK 47 | // 48 | this.btOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 49 | this.btOK.DialogResult = System.Windows.Forms.DialogResult.OK; 50 | this.btOK.Location = new System.Drawing.Point(278, 159); 51 | this.btOK.Name = "btOK"; 52 | this.btOK.Size = new System.Drawing.Size(75, 23); 53 | this.btOK.TabIndex = 3; 54 | this.btOK.Text = "OK"; 55 | this.btOK.UseVisualStyleBackColor = true; 56 | // 57 | // btCancel 58 | // 59 | this.btCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 60 | this.btCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 61 | this.btCancel.Location = new System.Drawing.Point(359, 159); 62 | this.btCancel.Name = "btCancel"; 63 | this.btCancel.Size = new System.Drawing.Size(75, 23); 64 | this.btCancel.TabIndex = 4; 65 | this.btCancel.Text = "Cancel"; 66 | this.btCancel.UseVisualStyleBackColor = true; 67 | // 68 | // FormRemoteAddEdit 69 | // 70 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 71 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 72 | this.ClientSize = new System.Drawing.Size(446, 194); 73 | this.Controls.Add(this.btOK); 74 | this.Controls.Add(this.btCancel); 75 | this.Controls.Add(this.remoteEdit); 76 | this.MaximizeBox = false; 77 | this.MinimizeBox = false; 78 | this.MinimumSize = new System.Drawing.Size(379, 232); 79 | this.Name = "FormRemoteAddEdit"; 80 | this.ShowIcon = false; 81 | this.ShowInTaskbar = false; 82 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 83 | this.Text = "Add/Edit"; 84 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormRemoteAddEditFormClosing); 85 | this.ResumeLayout(false); 86 | 87 | } 88 | 89 | #endregion 90 | 91 | private RemoteEdit remoteEdit; 92 | private System.Windows.Forms.Button btOK; 93 | private System.Windows.Forms.Button btCancel; 94 | 95 | } 96 | } -------------------------------------------------------------------------------- /FormRemoteAddEdit.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce 4 | { 5 | public partial class FormRemoteAddEdit : Form 6 | { 7 | /// 8 | /// Specifies one of 3 main functions that this form supports 9 | /// 10 | public enum Function { Add, Edit, Rename }; 11 | 12 | public FormRemoteAddEdit() 13 | { 14 | InitializeComponent(); 15 | ClassWinGeometry.Restore(this); 16 | } 17 | 18 | /// 19 | /// Form is closing. 20 | /// 21 | private void FormRemoteAddEditFormClosing(object sender, FormClosingEventArgs e) 22 | { 23 | ClassWinGeometry.Save(this); 24 | } 25 | 26 | public void Prepare(Function fn, ClassRemotes.Remote remote) 27 | { 28 | remoteEdit.Clear(); 29 | remoteEdit.AnyTextChanged += SomeTextChanged; 30 | 31 | // Do things differently basen on whether we are using this 32 | // form to add a new remote repo, rename it or we are editing 33 | // an existing remote repo 34 | 35 | switch (fn) 36 | { 37 | case Function.Add: 38 | remoteEdit.Enable(true, true); 39 | remote.Name = "origin"; 40 | remote.PushCmd = ""; 41 | remoteEdit.Set(remote); 42 | Text = "Add a new remote repository"; 43 | btOK.Enabled = false; 44 | break; 45 | case Function.Edit: 46 | Text = "Edit remote repository '" + remote.Name + "'"; 47 | remoteEdit.Enable(false, true); 48 | remoteEdit.Set(remote); 49 | break; 50 | case Function.Rename: 51 | Text = "Rename remote repository '" + remote.Name + "'"; 52 | remoteEdit.Enable(true, false); 53 | remoteEdit.Set(remote); 54 | break; 55 | } 56 | } 57 | 58 | /// 59 | /// Return the content of the remote repo specification structure 60 | /// 61 | /// Remote repo values 62 | public ClassRemotes.Remote Get() 63 | { 64 | return remoteEdit.Get(); 65 | } 66 | 67 | /// 68 | /// Callback function called when text in the remote repo editing 69 | /// has changed. Enable or disable OK button based on some simple 70 | /// checks. 71 | /// 72 | private void SomeTextChanged(bool valid) 73 | { 74 | btOK.Enabled = valid; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /FormRemoteEdit.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce 2 | { 3 | partial class FormRemoteEdit 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.userControlRemotesEdit = new GitForce.RemotesEdit(); 32 | this.btDone = new System.Windows.Forms.Button(); 33 | this.SuspendLayout(); 34 | // 35 | // _userControlRemotesEdit 36 | // 37 | this.userControlRemotesEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 38 | | System.Windows.Forms.AnchorStyles.Left) 39 | | System.Windows.Forms.AnchorStyles.Right))); 40 | this.userControlRemotesEdit.Location = new System.Drawing.Point(12, 12); 41 | this.userControlRemotesEdit.MinimumSize = new System.Drawing.Size(320, 165); 42 | this.userControlRemotesEdit.Name = "userControlRemotesEdit"; 43 | this.userControlRemotesEdit.Size = new System.Drawing.Size(542, 197); 44 | this.userControlRemotesEdit.TabIndex = 0; 45 | // 46 | // btDone 47 | // 48 | this.btDone.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 49 | this.btDone.DialogResult = System.Windows.Forms.DialogResult.OK; 50 | this.btDone.Location = new System.Drawing.Point(479, 215); 51 | this.btDone.Name = "btDone"; 52 | this.btDone.Size = new System.Drawing.Size(75, 23); 53 | this.btDone.TabIndex = 2; 54 | this.btDone.Text = "Done"; 55 | this.btDone.UseVisualStyleBackColor = true; 56 | // 57 | // FormRemoteEdit 58 | // 59 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 60 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 61 | this.CancelButton = this.btDone; 62 | this.ClientSize = new System.Drawing.Size(566, 247); 63 | this.Controls.Add(this.btDone); 64 | this.Controls.Add(this.userControlRemotesEdit); 65 | this.MaximizeBox = false; 66 | this.MinimizeBox = false; 67 | this.MinimumSize = new System.Drawing.Size(533, 285); 68 | this.Name = "FormRemoteEdit"; 69 | this.ShowIcon = false; 70 | this.ShowInTaskbar = false; 71 | this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; 72 | this.Text = "Edit Remote Repositories"; 73 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormRemoteEditFormClosing); 74 | this.ResumeLayout(false); 75 | 76 | } 77 | 78 | #endregion 79 | 80 | private RemotesEdit userControlRemotesEdit; 81 | private System.Windows.Forms.Button btDone; 82 | 83 | } 84 | } -------------------------------------------------------------------------------- /FormRemoteEdit.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce 4 | { 5 | public partial class FormRemoteEdit : Form 6 | { 7 | public FormRemoteEdit(ClassRepo repo) 8 | { 9 | InitializeComponent(); 10 | ClassWinGeometry.Restore(this); 11 | 12 | userControlRemotesEdit.SetRepo(repo); 13 | } 14 | 15 | /// 16 | /// Form is closing. 17 | /// 18 | private void FormRemoteEditFormClosing(object sender, FormClosingEventArgs e) 19 | { 20 | ClassWinGeometry.Save(this); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /FormRepoEdit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | using ControlGitconfig = GitForce.Repo.Edit.Panels.ControlGitconfig; 5 | using ControlGitignore = GitForce.Repo.Edit.Panels.ControlGitignore; 6 | using ControlUser = GitForce.Repo.Edit.Panels.ControlUser; 7 | using ControlLocal = GitForce.Repo.Edit.Panels.ControlLocal; 8 | using ControlRemotes = GitForce.Repo.Edit.Panels.ControlRemotes; 9 | 10 | namespace GitForce 11 | { 12 | /// 13 | /// Define an interface for option panels; at minimum they need to 14 | /// implement function that initializes and sets the changed values 15 | /// 16 | interface IRepoSettings 17 | { 18 | void Init(ClassRepo repo); 19 | void Focus(bool focused); 20 | void ApplyChanges(ClassRepo repo); 21 | } 22 | 23 | public partial class FormRepoEdit : Form 24 | { 25 | /// 26 | /// Create a lookup from panel names (which are set in each corresponding node 27 | /// of an setting tree view) to the actual repo edit panel instance: 28 | /// 29 | private readonly Dictionary panels = new Dictionary { 30 | { "Local", new ControlLocal() }, 31 | { "User", new ControlUser() }, 32 | { "Gitignore", new ControlGitignore() }, 33 | { "Gitconfig", new ControlGitconfig() }, 34 | { "Remotes", new ControlRemotes() }, 35 | }; 36 | 37 | /// 38 | /// Settings panel that is currently on the top 39 | /// 40 | private UserControl current; 41 | 42 | /// 43 | /// Current repo that we are editing 44 | /// 45 | private readonly ClassRepo repo; 46 | 47 | public FormRepoEdit(ClassRepo targetRepo) 48 | { 49 | InitializeComponent(); 50 | ClassWinGeometry.Restore(this); 51 | repo = targetRepo; 52 | 53 | // Add all user panels to the base repo edit panel; call their init 54 | foreach (KeyValuePair key in panels) 55 | { 56 | panel.Controls.Add(key.Value); 57 | (key.Value as IRepoSettings).Init(repo); 58 | key.Value.Dock = DockStyle.Fill; 59 | } 60 | 61 | // Expand the tree and select the first node 62 | treeSections.ExpandAll(); 63 | treeSections.SelectedNode = treeSections.Nodes[0].Nodes[0]; 64 | } 65 | 66 | /// 67 | /// Form is closing. 68 | /// 69 | private void FormRepoEditFormClosing(object sender, FormClosingEventArgs e) 70 | { 71 | ClassWinGeometry.Save(this); 72 | } 73 | 74 | /// 75 | /// Selecting the tree node brings up the corresponding user control 76 | /// 77 | private void TreeSectionsAfterSelect(object sender, TreeViewEventArgs e) 78 | { 79 | string panelName = e.Node.Tag as string; 80 | if (panelName != null && panels.ContainsKey(panelName)) 81 | { 82 | if (current != null) 83 | (current as IRepoSettings).Focus(false); 84 | current = panels[panelName]; 85 | current.BringToFront(); 86 | (current as IRepoSettings).Focus(true); 87 | } 88 | } 89 | 90 | /// 91 | /// User clicked on the Apply button - store all changes to the current 92 | /// setting panel, but not to any other. Hitting OK will store all panels. 93 | /// Hitting Cancel will void all changes in any panel done since the last 94 | /// time Apply button was pressed. 95 | /// 96 | private void BtApplyClick(object sender, EventArgs e) 97 | { 98 | (current as IRepoSettings).ApplyChanges(repo); 99 | } 100 | 101 | /// 102 | /// User clicked on the OK button - apply all modified settings before 103 | /// returning from the dialog 104 | /// 105 | private void BtOkClick(object sender, EventArgs e) 106 | { 107 | foreach (KeyValuePair key in panels) 108 | (key.Value as IRepoSettings).ApplyChanges(repo); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /FormReset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce 5 | { 6 | public partial class FormReset : Form 7 | { 8 | /// 9 | /// Command string that is being built based on the selected options 10 | /// 11 | public string Cmd = ""; 12 | 13 | public FormReset() 14 | { 15 | InitializeComponent(); 16 | ClassWinGeometry.Restore(this); 17 | } 18 | 19 | /// 20 | /// Form is closing. 21 | /// 22 | private void FormResetFormClosing(object sender, FormClosingEventArgs e) 23 | { 24 | ClassWinGeometry.Save(this); 25 | } 26 | 27 | /// 28 | /// Radio button to select reset type has been changed 29 | /// 30 | private void RadioButtonCheckedChanged(object sender, EventArgs e) 31 | { 32 | RadioButton rb = sender as RadioButton; 33 | if (rb.Checked) 34 | { 35 | switch (rb.Tag.ToString()) 36 | { 37 | case "0": 38 | Cmd = "--soft"; 39 | break; 40 | case "1": 41 | Cmd = "--mixed"; 42 | break; 43 | case "2": 44 | Cmd = "--hard"; 45 | break; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /FormStash.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce 5 | { 6 | /// 7 | /// Form implementing the git stash command 8 | /// 9 | public partial class FormStash : Form 10 | { 11 | public FormStash() 12 | { 13 | InitializeComponent(); 14 | ClassWinGeometry.Restore(this); 15 | } 16 | 17 | /// 18 | /// Form is closing. 19 | /// 20 | private void FormStashFormClosing(object sender, FormClosingEventArgs e) 21 | { 22 | ClassWinGeometry.Save(this); 23 | } 24 | 25 | /// 26 | /// User clicked on the stash button to stash files 27 | /// 28 | private void BtStashClick(object sender, EventArgs e) 29 | { 30 | string cmd = String.Format("stash save {0} {1}", 31 | checkKeepIndex.Checked ? "--keep-index" : "", 32 | string.IsNullOrEmpty(textName.Text) ? "" : textName.Text); 33 | 34 | App.Repos.Current.RunCmd(cmd); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /FormSwitchToBranch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce 5 | { 6 | /// 7 | /// Form to switch a branch to the one selected 8 | /// 9 | public partial class FormSwitchToBranch : Form 10 | { 11 | /// 12 | /// Singular branch name that is selected to be switched to 13 | /// 14 | private string branchName; 15 | 16 | public FormSwitchToBranch() 17 | { 18 | InitializeComponent(); 19 | ClassWinGeometry.Restore(this); 20 | 21 | // Initialize the list of local branches to switch to 22 | foreach (var branch in App.Repos.Current.Branches.Local) 23 | listBranches.Items.Add(branch); 24 | } 25 | 26 | /// 27 | /// Form is closing. 28 | /// 29 | private void FormSwitchToBranchFormClosing(object sender, FormClosingEventArgs e) 30 | { 31 | ClassWinGeometry.Save(this); 32 | } 33 | 34 | /// 35 | /// Button is clicked to switch to a (local) branch 36 | /// 37 | private void SwitchBranchClick(object sender, EventArgs e) 38 | { 39 | // Execute the final branch command 40 | App.Repos.Current.Branches.SwitchTo(branchName); 41 | } 42 | 43 | /// 44 | /// Store the selected branch 45 | /// 46 | private void ListBranchesSelectedIndexChanged(object sender, EventArgs e) 47 | { 48 | branchName = listBranches.SelectedItem.ToString(); 49 | btSwitch.Enabled = true; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /FormUnstash.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce 5 | { 6 | /// 7 | /// Form implementing the git unstash command 8 | /// 9 | public partial class FormUnstash : Form 10 | { 11 | /// 12 | /// Currently selected stash string (stash id part only) 13 | /// 14 | private string stash; 15 | 16 | public FormUnstash() 17 | { 18 | InitializeComponent(); 19 | ClassWinGeometry.Restore(this); 20 | 21 | PopulateStashList(); 22 | } 23 | 24 | /// 25 | /// Form is closing. 26 | /// 27 | private void FormUnstashFormClosing(object sender, FormClosingEventArgs e) 28 | { 29 | ClassWinGeometry.Save(this); 30 | } 31 | 32 | /// 33 | /// Populate list with existing stashes 34 | /// 35 | private void PopulateStashList() 36 | { 37 | listStashes.Items.Clear(); 38 | ExecResult result = App.Repos.Current.Run("stash list"); 39 | if (result.Success()) 40 | { 41 | string[] response = result.stdout.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 42 | foreach (var stash in response) 43 | listStashes.Items.Add(stash); 44 | } 45 | // Disable buttons (in the case the stash list was empty) 46 | // but re-enable them once we have a stash to select (select the top one by default) 47 | btApply.Enabled = btRemove.Enabled = btShow.Enabled = false; 48 | if (listStashes.Items.Count > 0) 49 | { 50 | string s = listStashes.Items[0].ToString(); 51 | stash = s.Substring(0, s.IndexOf(':')); 52 | listStashes.SelectedIndex = 0; 53 | btApply.Enabled = btRemove.Enabled = btShow.Enabled = true; 54 | } 55 | } 56 | 57 | /// 58 | /// User clicked on one of the selected stash entries. 59 | /// Set the proper control enables. 60 | /// 61 | private void ListStashesSelectedIndexChanged(object sender, EventArgs e) 62 | { 63 | string s = listStashes.SelectedItem.ToString(); 64 | stash = s.Substring(0, s.IndexOf(':')); 65 | } 66 | 67 | /// 68 | /// Apply the selected stash 69 | /// 70 | private void BtUnstashClick(object sender, EventArgs e) 71 | { 72 | string cmd = String.Format("stash {0} {1}", 73 | checkKeepStash.Checked ? "apply" : "pop", 74 | stash); 75 | App.Repos.Current.RunCmd(cmd); 76 | } 77 | 78 | /// 79 | /// Remove selected stash from the list of stashes 80 | /// 81 | private void BtRemoveClick(object sender, EventArgs e) 82 | { 83 | string cmd = "stash drop " + stash; 84 | App.Repos.Current.RunCmd(cmd); 85 | PopulateStashList(); 86 | } 87 | 88 | /// 89 | /// Show more information on the selected stash 90 | /// 91 | private void BtShowClick(object sender, EventArgs e) 92 | { 93 | FormShowChangelist formShowChangelist = new FormShowChangelist(); 94 | DialogResult result; 95 | do 96 | { 97 | formShowChangelist.LoadChangelist(stash); 98 | 99 | // Walk the list of stashes up and down 100 | result = formShowChangelist.ShowDialog(); 101 | if (result == DialogResult.No) 102 | { 103 | if (listStashes.SelectedIndex < listStashes.Items.Count - 1) 104 | listStashes.SelectedIndex++; 105 | } 106 | if (result == DialogResult.Yes) 107 | { 108 | if (listStashes.SelectedIndex > 0) 109 | listStashes.SelectedIndex--; 110 | } 111 | } while (result != DialogResult.Cancel); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /GitForce.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GitForce", "GitForce.csproj", "{4C92D7E3-885E-4A70-9E56-13DAD0BCF8D7}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x86 = Debug|x86 9 | Release|x86 = Release|x86 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {4C92D7E3-885E-4A70-9E56-13DAD0BCF8D7}.Debug|x86.ActiveCfg = Debug|x86 13 | {4C92D7E3-885E-4A70-9E56-13DAD0BCF8D7}.Debug|x86.Build.0 = Debug|x86 14 | {4C92D7E3-885E-4A70-9E56-13DAD0BCF8D7}.Release|x86.ActiveCfg = Release|x86 15 | {4C92D7E3-885E-4A70-9E56-13DAD0BCF8D7}.Release|x86.Build.0 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /ListBoxEx.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce 5 | { 6 | /// 7 | /// Subclass a standard ListBox to be able to set some internal flags to avoid flicker 8 | /// http://yacsharpblog.blogspot.com/2008/07/listbox-flicker.html 9 | /// 10 | internal class ListBoxEx : ListBox 11 | { 12 | public ListBoxEx() 13 | { 14 | this.SetStyle( 15 | ControlStyles.OptimizedDoubleBuffer | 16 | ControlStyles.ResizeRedraw | 17 | ControlStyles.UserPaint, 18 | true); 19 | this.DrawMode = DrawMode.OwnerDrawFixed; 20 | } 21 | 22 | protected override void OnDrawItem(DrawItemEventArgs e) 23 | { 24 | if (this.Items.Count > 0 && e.Index>=0) 25 | { 26 | e.DrawBackground(); 27 | e.Graphics.DrawString(this.Items[e.Index].ToString(), e.Font, new SolidBrush(this.ForeColor), new PointF(e.Bounds.X, e.Bounds.Y)); 28 | } 29 | base.OnDrawItem(e); 30 | } 31 | 32 | protected override void OnPaint(PaintEventArgs e) 33 | { 34 | Region iRegion = new Region(e.ClipRectangle); 35 | e.Graphics.FillRegion(new SolidBrush(this.BackColor), iRegion); 36 | if (this.Items.Count > 0) 37 | { 38 | for (int i = 0; i < this.Items.Count; ++i) 39 | { 40 | System.Drawing.Rectangle irect = this.GetItemRectangle(i); 41 | if (e.ClipRectangle.IntersectsWith(irect)) 42 | { 43 | if ((this.SelectionMode == SelectionMode.One && this.SelectedIndex == i) 44 | || (this.SelectionMode == SelectionMode.MultiSimple && this.SelectedIndices.Contains(i)) 45 | || (this.SelectionMode == SelectionMode.MultiExtended && this.SelectedIndices.Contains(i))) 46 | { 47 | OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font, 48 | irect, i, 49 | DrawItemState.Selected, this.ForeColor, 50 | this.BackColor)); 51 | } 52 | else 53 | { 54 | OnDrawItem(new DrawItemEventArgs(e.Graphics, this.Font, 55 | irect, i, 56 | DrawItemState.Default, this.ForeColor, 57 | this.BackColor)); 58 | } 59 | iRegion.Complement(irect); 60 | } 61 | } 62 | } 63 | base.OnPaint(e); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /ListViewEx.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce 4 | { 5 | /// 6 | /// Subclass a standard ListView to be able to set some internal flags 7 | /// 8 | public class ListViewEx : ListView 9 | { 10 | public ListViewEx() 11 | : base() 12 | { 13 | // Optimize drawing to avoid flicker 14 | SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 15 | SetStyle(ControlStyles.AllPaintingInWmPaint, true); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("GitForce")] 8 | [assembly: AssemblyDescription("A Visual Git Frontend Tool")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("GitForce")] 11 | [assembly: AssemblyProduct("GitForce built on 2024/09/07")] 12 | [assembly: AssemblyCopyright("Written by Goran Devic, released under GPL")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("ac46f858-a555-4b13-9a78-700d6dfaabb4")] 23 | 24 | // Remains fixed as application persistent settings are keyed off this number 25 | [assembly: AssemblyVersion("1.0.0.0")] 26 | 27 | // Effective application version number 28 | [assembly: AssemblyFileVersion("1.0.61")] 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitForce 2 | 3 | GitForce is a GUI front-ends for the git command line tool. GitForce runs on both Windows and Linux. 4 | 5 | ## Features 6 | 7 | * Single executable file with no need for installation, portable by design 8 | * Intuitive GUI with efficient drag and drop for most operations 9 | * Runs on Windows and Linux (using Mono) and on other OS-es with Mono support 10 | * Easy way to manage multiple git repos 11 | * Multiple sets of repos (workspaces) 12 | * Custom tools, menus and extensions tailoring it to your specific needs 13 | * Easy managing of SSH keys and remotes 14 | * Integrated git command line interface 15 | * Users familiar with Perforce will find this UI very familiar! 16 | 17 | ## Links 18 | 19 | * Documentation [link](https://sites.google.com/site/gitforcetool/home) 20 | * Forum [link](https://sourceforge.net/p/gitforce/discussion) 21 | 22 | ## Running GitForce.exe on Linux (and other Mono) environments 23 | 24 | GitForce.exe needs Mono support, 'git' and one of the diff-tool packages: 25 | ``` 26 | $ sudo apt-get install mono-complete git meld 27 | ``` 28 | 29 | ## Building from sources 30 | 31 | On Windows OS, install MSVC 2015 (other versions may also work) and open GitForce.sln. 32 | 33 | On Linux, use xbuild (part of mono-complete): 34 | ``` 35 | $ xbuild /p:Configuration=Release GitForce.sln 36 | ``` 37 | 38 | The current code has been developed (and built) on Windows. The same binary works on Linux (using Mono). 39 | It should also work on other OS-es that have Mono support. 40 | 41 | ## Screenshot 42 | 43 | 44 | -------------------------------------------------------------------------------- /Release.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Release script for MS Windows 3 | # 4 | # * Runs MSBuild to compile GitForce release version 5 | # * Increments the version number and sets the build date in AssemblyInfo.cs file 6 | # * Gets the log of changes since last release and formats changes.txt to be used as a release commit text 7 | # 8 | import sys, time, datetime, os, subprocess, re, shutil 9 | 10 | def IncrementVersion(file, change): 11 | # Open the changelist file to write 12 | fch = open(change, "wt") 13 | # Save the original version file since it will be modified 14 | file_backup = file+"~" 15 | if(os.path.exists(file_backup)): 16 | os.remove(file_backup) 17 | os.rename(file, file_backup) 18 | fin = open(file_backup) 19 | fout = open(file, "wt") 20 | # Find version and build date and update them 21 | for line in fin: 22 | 23 | if line.find("AssemblyFileVersion")>0: 24 | p = re.compile(r'\W+') 25 | ver = p.split(line) 26 | print('Major = ', ver[3]) 27 | print('Minor = ', ver[4]) 28 | print('Build = ', ver[5], ' -> ', int(ver[5])+1) 29 | release = ver[3]+'.'+ver[4]+'.'+str(int(ver[5])+1) 30 | line = line.replace(ver[3]+'.'+ver[4]+'.'+ver[5], release) 31 | 32 | if line.find("AssemblyProduct")>0: 33 | now = datetime.datetime.now() 34 | format = "%Y/%m/%d" 35 | built = now.strftime(format) 36 | print('Setting the Build date = ', built) 37 | line = "[assembly: AssemblyProduct(\"GitForce built on " + built + "\")]\n" 38 | 39 | fout.write(line) 40 | fin.close() 41 | fout.close() 42 | fch.write("### Release " + release + " (" + built + ")\n") 43 | fch.close(); 44 | return release 45 | 46 | def IncrementVersionXml(file, version): 47 | # Save the original file before modifying it 48 | file_backup = file+"~" 49 | if(os.path.exists(file_backup)): 50 | os.remove(file_backup) 51 | os.rename(file, file_backup) 52 | fin = open(file_backup) 53 | fout = open(file, "wt") 54 | # Find version and build date and update them 55 | for line in fin: 56 | pos = line.find("") 57 | if pos > 0: 58 | line = " " * pos 59 | line = line + "" + version + "\n" 60 | fout.write(line) 61 | fin.close() 62 | fout.close() 63 | 64 | version_file = "Properties/AssemblyInfo.cs" 65 | changelist_file = "change.txt" 66 | 67 | version = IncrementVersion(version_file, changelist_file) 68 | print('Building:') 69 | subprocess.Popen(["MSBuild.exe", "/t:Rebuild", "/p:Configuration=Release"], shell=True).wait() 70 | 71 | # Copy released executable 72 | shutil.copy2("obj/x86/Release/GitForce.exe", "./") # Here, to the root of the project 73 | 74 | # Get the summary of changes and append to the subject 75 | proc = subprocess.Popen(["git", "log", "--format=%B"], stdout=subprocess.PIPE) 76 | stdout = proc.communicate()[0].decode('windows-1252') 77 | stdout = stdout[0:stdout.find("###")] 78 | 79 | h = open(changelist_file, "a") 80 | h.write("-------------------------------------------\n") 81 | h.write("SUMMARY OF CHANGES:\n\n") 82 | h.write(stdout) 83 | h.close() 84 | 85 | print('-------------------------------------------') 86 | print('Submit ' + version_file) 87 | print('using the description in ' + changelist_file) 88 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlGitconfig.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Repo.Edit.Panels 2 | { 3 | partial class ControlGitconfig 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.userControlEditFile = new GitForce.UserControlEditFile(); 32 | this.SuspendLayout(); 33 | // 34 | // userControlEditFile 35 | // 36 | this.userControlEditFile.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.userControlEditFile.Location = new System.Drawing.Point(0, 0); 38 | this.userControlEditFile.Name = "userControlEditFile"; 39 | this.userControlEditFile.Size = new System.Drawing.Size(300, 300); 40 | this.userControlEditFile.TabIndex = 0; 41 | this.userControlEditFile.Tag = ""; 42 | // 43 | // ControlGitconfig 44 | // 45 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 46 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 47 | this.Controls.Add(this.userControlEditFile); 48 | this.Name = "ControlGitconfig"; 49 | this.Size = new System.Drawing.Size(300, 300); 50 | this.ResumeLayout(false); 51 | 52 | } 53 | 54 | #endregion 55 | 56 | private UserControlEditFile userControlEditFile; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlGitconfig.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Repo.Edit.Panels 5 | { 6 | public partial class ControlGitconfig : UserControl, IRepoSettings 7 | { 8 | /// 9 | /// File containing repo git config settings 10 | /// 11 | private string configFile; 12 | 13 | public ControlGitconfig() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | /// 19 | /// Initialize pertinent settings 20 | /// 21 | public void Init(ClassRepo repo) 22 | { 23 | configFile = repo.Path + Path.DirectorySeparatorChar + 24 | ".git" + Path.DirectorySeparatorChar + 25 | "config"; 26 | } 27 | 28 | /// 29 | /// Control received a focus (true) or lost a focus (false) 30 | /// 31 | public void Focus(bool focused) 32 | { 33 | if (focused) 34 | userControlEditFile.LoadFile(configFile); 35 | else 36 | { 37 | // As the control is losing its focus, if the text was changed, ask the user 38 | // to save the changes or not. This behavior is a special case since we need 39 | // to make changes to this config file atomic. 40 | if (userControlEditFile.Dirty) 41 | { 42 | if (MessageBox.Show("Save changes to the configuration file?", "Edit config", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 43 | userControlEditFile.SaveFile(configFile); 44 | else 45 | userControlEditFile.LoadFile(configFile); 46 | } 47 | } 48 | } 49 | 50 | /// 51 | /// Apply changed settings 52 | /// 53 | public void ApplyChanges(ClassRepo repo) 54 | { 55 | if (userControlEditFile.Dirty) 56 | userControlEditFile.SaveFile(configFile); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlGitignore.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Repo.Edit.Panels 2 | { 3 | partial class ControlGitignore 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.userControlEditGitignore = new UserControlEditGitignore(); 32 | this.SuspendLayout(); 33 | // 34 | // userControlEditGitignore 35 | // 36 | this.userControlEditGitignore.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.userControlEditGitignore.Location = new System.Drawing.Point(0, 0); 38 | this.userControlEditGitignore.Name = "userControlEditGitignore"; 39 | this.userControlEditGitignore.Size = new System.Drawing.Size(300, 300); 40 | this.userControlEditGitignore.TabIndex = 0; 41 | // 42 | // ControlGitignore 43 | // 44 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 45 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 46 | this.Controls.Add(this.userControlEditGitignore); 47 | this.Name = "ControlGitignore"; 48 | this.Size = new System.Drawing.Size(300, 300); 49 | this.ResumeLayout(false); 50 | 51 | } 52 | 53 | #endregion 54 | 55 | private UserControlEditGitignore userControlEditGitignore; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlGitignore.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Repo.Edit.Panels 5 | { 6 | public partial class ControlGitignore : UserControl, IRepoSettings 7 | { 8 | /// 9 | /// File containing the excludes patterns 10 | /// 11 | private string excludesFile; 12 | 13 | public ControlGitignore() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | /// 19 | /// Initialize pertinent settings 20 | /// 21 | public void Init(ClassRepo repo) 22 | { 23 | excludesFile = repo.Path + Path.DirectorySeparatorChar + 24 | ".git" + Path.DirectorySeparatorChar + 25 | "info" + Path.DirectorySeparatorChar + 26 | "exclude"; 27 | userControlEditGitignore.LoadGitIgnore(excludesFile); 28 | } 29 | 30 | /// 31 | /// Control received a focus (true) or lost a focus (false) 32 | /// 33 | public void Focus(bool focused) 34 | { 35 | } 36 | 37 | /// 38 | /// Apply changed settings 39 | /// 40 | public void ApplyChanges(ClassRepo repo) 41 | { 42 | userControlEditGitignore.SaveGitIgnore(excludesFile); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlLocal.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce.Repo.Edit.Panels 4 | { 5 | public partial class ControlLocal : UserControl, IRepoSettings 6 | { 7 | public ControlLocal() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | /// 13 | /// Keeps the local settings of line endings 14 | /// 15 | private string crlf; 16 | 17 | /// 18 | /// Initialize pertinent settings 19 | /// 20 | public void Init(ClassRepo repo) 21 | { 22 | // Initialize the line endings radio buttons 23 | crlf = ClassConfig.GetLocal(repo, "core.autocrlf"); 24 | if (crlf == "true") radio1.Checked = true; 25 | if (crlf == "input") radio2.Checked = true; 26 | if (crlf == "false") radio3.Checked = true; 27 | } 28 | 29 | /// 30 | /// Control received a focus (true) or lost a focus (false) 31 | /// 32 | public void Focus(bool focused) 33 | { 34 | } 35 | 36 | /// 37 | /// Apply changed settings 38 | /// 39 | public void ApplyChanges(ClassRepo repo) 40 | { 41 | string newCrlf = string.Empty; // Default 42 | if (radio1.Checked) newCrlf = "true"; 43 | if (radio2.Checked) newCrlf = "input"; 44 | if (radio3.Checked) newCrlf = "false"; 45 | if (radio4.Checked) newCrlf = string.Empty; // This value will remove the setting 46 | 47 | if (newCrlf != crlf) 48 | ClassConfig.SetLocal(repo, "core.autocrlf", newCrlf); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlRemotes.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Repo.Edit.Panels 2 | { 3 | partial class ControlRemotes 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.listRemotes = new System.Windows.Forms.ListBox(); 33 | this.btEdit = new System.Windows.Forms.Button(); 34 | this.SuspendLayout(); 35 | // 36 | // label1 37 | // 38 | this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 39 | | System.Windows.Forms.AnchorStyles.Right))); 40 | this.label1.BackColor = System.Drawing.SystemColors.Info; 41 | this.label1.Location = new System.Drawing.Point(0, 0); 42 | this.label1.Name = "label1"; 43 | this.label1.Size = new System.Drawing.Size(300, 30); 44 | this.label1.TabIndex = 14; 45 | this.label1.Text = "Show and edit remote git repositories for this repo."; 46 | // 47 | // listRemotes 48 | // 49 | this.listRemotes.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 50 | | System.Windows.Forms.AnchorStyles.Left) 51 | | System.Windows.Forms.AnchorStyles.Right))); 52 | this.listRemotes.FormattingEnabled = true; 53 | this.listRemotes.IntegralHeight = false; 54 | this.listRemotes.Location = new System.Drawing.Point(3, 33); 55 | this.listRemotes.Name = "listRemotes"; 56 | this.listRemotes.SelectionMode = System.Windows.Forms.SelectionMode.None; 57 | this.listRemotes.Size = new System.Drawing.Size(294, 235); 58 | this.listRemotes.TabIndex = 15; 59 | // 60 | // btEdit 61 | // 62 | this.btEdit.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 63 | | System.Windows.Forms.AnchorStyles.Right))); 64 | this.btEdit.Location = new System.Drawing.Point(3, 274); 65 | this.btEdit.Name = "btEdit"; 66 | this.btEdit.Size = new System.Drawing.Size(294, 23); 67 | this.btEdit.TabIndex = 16; 68 | this.btEdit.Text = "Edit Remotes"; 69 | this.btEdit.UseVisualStyleBackColor = true; 70 | this.btEdit.Click += new System.EventHandler(this.BtEditClick); 71 | // 72 | // ControlRemotes 73 | // 74 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 75 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 76 | this.Controls.Add(this.btEdit); 77 | this.Controls.Add(this.listRemotes); 78 | this.Controls.Add(this.label1); 79 | this.Name = "ControlRemotes"; 80 | this.Size = new System.Drawing.Size(300, 300); 81 | this.ResumeLayout(false); 82 | 83 | } 84 | 85 | #endregion 86 | 87 | private System.Windows.Forms.Label label1; 88 | private System.Windows.Forms.ListBox listRemotes; 89 | private System.Windows.Forms.Button btEdit; 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlRemotes.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce.Repo.Edit.Panels 4 | { 5 | public partial class ControlRemotes : UserControl, IRepoSettings 6 | { 7 | private ClassRepo currentRepo; 8 | 9 | public ControlRemotes() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | /// 15 | /// Initialize pertinent settings 16 | /// 17 | public void Init(ClassRepo repo) 18 | { 19 | currentRepo = repo; 20 | 21 | currentRepo.Remotes.Refresh(currentRepo); 22 | 23 | listRemotes.BeginUpdate(); 24 | listRemotes.Items.Clear(); 25 | 26 | // Get the list of names from remotes class and iteratively add them to the listbox 27 | foreach (var r in currentRepo.Remotes.GetListNames()) 28 | listRemotes.Items.Add(r); 29 | 30 | listRemotes.EndUpdate(); 31 | } 32 | 33 | /// 34 | /// Control received a focus (true) or lost a focus (false) 35 | /// 36 | public void Focus(bool focused) 37 | { 38 | } 39 | 40 | /// 41 | /// Apply changed settings 42 | /// 43 | public void ApplyChanges(ClassRepo repo) 44 | { 45 | } 46 | 47 | /// 48 | /// User clicked on the edit remote repos, open that dialog. 49 | /// 50 | private void BtEditClick(object sender, System.EventArgs e) 51 | { 52 | FormRemoteEdit remoteEdit = new FormRemoteEdit(currentRepo); 53 | if (remoteEdit.ShowDialog() == DialogResult.OK) 54 | App.DoRefresh(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Repo.Edit.Panels/ControlUser.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce.Repo.Edit.Panels 4 | { 5 | public partial class ControlUser : UserControl, IRepoSettings 6 | { 7 | public ControlUser() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | /// 13 | /// Initialize pertinent settings 14 | /// 15 | public void Init(ClassRepo repo) 16 | { 17 | textBoxUserName.Text = ClassConfig.GetLocal(repo, "user.name"); 18 | textBoxUserEmail.Text = ClassConfig.GetLocal(repo, "user.email"); 19 | 20 | // Add the dirty (modified) value changed helper 21 | textBoxUserName.TextChanged += ControlDirtyHelper.ControlDirty; 22 | textBoxUserEmail.TextChanged += ControlDirtyHelper.ControlDirty; 23 | } 24 | 25 | /// 26 | /// Control received a focus (true) or lost a focus (false) 27 | /// 28 | public void Focus(bool focused) 29 | { 30 | } 31 | 32 | /// 33 | /// Apply changed settings 34 | /// 35 | public void ApplyChanges(ClassRepo repo) 36 | { 37 | if (textBoxUserName.Tag != null) 38 | { 39 | // Change the repo config and our internal variable so we dont need to reload 40 | ClassConfig.SetLocal(repo, "user.name", textBoxUserName.Text.Trim()); 41 | repo.UserName = textBoxUserName.Text; 42 | textBoxUserName.Tag = null; 43 | } 44 | 45 | if (textBoxUserEmail.Tag != null) 46 | { 47 | // Change the repo config and our internal variable so we dont need to reload 48 | ClassConfig.SetLocal(repo, "user.email", textBoxUserEmail.Text.Trim()); 49 | repo.UserEmail = textBoxUserEmail.Text; 50 | textBoxUserEmail.Tag = null; 51 | } 52 | } 53 | 54 | /// 55 | /// Copy global user name and email address settings 56 | /// 57 | private void CopyGlobal(object sender, System.EventArgs e) 58 | { 59 | textBoxUserName.Text = ClassConfig.GetGlobal("user.name"); 60 | textBoxUserEmail.Text = ClassConfig.GetGlobal("user.email"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Resources/.gitattributes: -------------------------------------------------------------------------------- 1 | *.sh text eol=lf 2 | -------------------------------------------------------------------------------- /Resources/App/1475_Text Balloon_48x48.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/1475_Text Balloon_48x48.ico -------------------------------------------------------------------------------- /Resources/App/eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/eye.png -------------------------------------------------------------------------------- /Resources/App/file_missing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/file_missing.png -------------------------------------------------------------------------------- /Resources/App/git.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/git.ico -------------------------------------------------------------------------------- /Resources/App/pulldown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/pulldown.png -------------------------------------------------------------------------------- /Resources/App/update.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/update.gif -------------------------------------------------------------------------------- /Resources/App/world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/App/world.png -------------------------------------------------------------------------------- /Resources/Artwork/GitForceLogo-large.lds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Artwork/GitForceLogo-large.lds -------------------------------------------------------------------------------- /Resources/Artwork/GitForceLogo-small.lds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Artwork/GitForceLogo-small.lds -------------------------------------------------------------------------------- /Resources/Artwork/gif/GitForceLogo-large.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Artwork/gif/GitForceLogo-large.gif -------------------------------------------------------------------------------- /Resources/Artwork/png/GitForceLogo-dl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Artwork/png/GitForceLogo-dl.png -------------------------------------------------------------------------------- /Resources/Artwork/png/GitForceLogo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Artwork/png/GitForceLogo-small.png -------------------------------------------------------------------------------- /Resources/Artwork/png/GitForceLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Artwork/png/GitForceLogo.png -------------------------------------------------------------------------------- /Resources/Artwork/readme.txt: -------------------------------------------------------------------------------- 1 | The application icon set was created using the "Logo Design Studio": 2 | http://www.summitsoft.com/ 3 | 4 | Icons were exported as PNG at the resolution of 1024x1024 and then rescaled 5 | using this website: http://iconverticons.com/online/ 6 | 7 | Finally, a selected set of sizes was recombined into a single application 8 | icon using this website: http://convertico.org/Multi_Image_to_one_icon/ 9 | -------------------------------------------------------------------------------- /Resources/Branch/112_RightArrowLong_Green_16x16_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Branch/112_RightArrowLong_Green_16x16_72.png -------------------------------------------------------------------------------- /Resources/Branch/112_RightArrowLong_Grey_16x16_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Branch/112_RightArrowLong_Grey_16x16_72.png -------------------------------------------------------------------------------- /Resources/Branch/branch.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Branch/branch.bmp -------------------------------------------------------------------------------- /Resources/Changelist/112_DownArrowShort_Blue_16x16_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/112_DownArrowShort_Blue_16x16_72.png -------------------------------------------------------------------------------- /Resources/Changelist/112_UpArrowShort_Blue_16x16_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/112_UpArrowShort_Blue_16x16_72.png -------------------------------------------------------------------------------- /Resources/Changelist/Change0.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/Change0.ico -------------------------------------------------------------------------------- /Resources/Changelist/Change1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/Change1.ico -------------------------------------------------------------------------------- /Resources/Changelist/Journal.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/Journal.ico -------------------------------------------------------------------------------- /Resources/Changelist/search.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/search.ico -------------------------------------------------------------------------------- /Resources/Changelist/xsearch.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Changelist/xsearch.ico -------------------------------------------------------------------------------- /Resources/File/document.revert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/document.revert.png -------------------------------------------------------------------------------- /Resources/File/document_a4_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/document_a4_add.png -------------------------------------------------------------------------------- /Resources/File/document_a4_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/document_a4_remove.png -------------------------------------------------------------------------------- /Resources/File/document_letter_forward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/document_letter_forward.png -------------------------------------------------------------------------------- /Resources/File/documents_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/documents_add.png -------------------------------------------------------------------------------- /Resources/File/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/download.png -------------------------------------------------------------------------------- /Resources/File/pencil.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/pencil.png -------------------------------------------------------------------------------- /Resources/File/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/remove.png -------------------------------------------------------------------------------- /Resources/File/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/File/upload.png -------------------------------------------------------------------------------- /Resources/PuTTY/PAGEANT.ICO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/PuTTY/PAGEANT.ICO -------------------------------------------------------------------------------- /Resources/PuTTY/PUTTYGEN.ICO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/PuTTY/PUTTYGEN.ICO -------------------------------------------------------------------------------- /Resources/PuTTY/pageant.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/PuTTY/pageant.exe -------------------------------------------------------------------------------- /Resources/PuTTY/plink.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/PuTTY/plink.exe -------------------------------------------------------------------------------- /Resources/PuTTY/puttygen.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/PuTTY/puttygen.exe -------------------------------------------------------------------------------- /Resources/Repo/Repo0.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Repo/Repo0.ico -------------------------------------------------------------------------------- /Resources/Repo/Repo1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Repo/Repo1.ico -------------------------------------------------------------------------------- /Resources/Repo/Repo2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Repo/Repo2.ico -------------------------------------------------------------------------------- /Resources/Repo/Repo3.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Repo/Repo3.ico -------------------------------------------------------------------------------- /Resources/SSH/git-ssh-helper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec ssh -o StrictHostKeyChecking=no "$@" -------------------------------------------------------------------------------- /Resources/Toolstrip/Change0.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Toolstrip/Change0.ico -------------------------------------------------------------------------------- /Resources/Toolstrip/Gear.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Toolstrip/Gear.ico -------------------------------------------------------------------------------- /Resources/Toolstrip/branch.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Toolstrip/branch.bmp -------------------------------------------------------------------------------- /Resources/Toolstrip/eventlogError.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Toolstrip/eventlogError.ico -------------------------------------------------------------------------------- /Resources/Toolstrip/key.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Toolstrip/key.ico -------------------------------------------------------------------------------- /Resources/Toolstrip/keys.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Toolstrip/keys.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconA.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconA.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconC.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconC.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconD.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconD.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconDB.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconDB.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconFC.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconFC.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconFCM.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconFCM.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconFF.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconFF.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconFO.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconFO.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconFOM.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconFOM.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconM.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconM.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconQ.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconQ.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconR.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconR.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconU.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconU.ico -------------------------------------------------------------------------------- /Resources/Tree/TreeIconX.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/Tree/TreeIconX.ico -------------------------------------------------------------------------------- /Resources/View/112_RefreshArrow_Blue.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/View/112_RefreshArrow_Blue.ico -------------------------------------------------------------------------------- /Resources/View/Scroll.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/View/Scroll.ico -------------------------------------------------------------------------------- /Resources/View/openHS.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/Resources/View/openHS.bmp -------------------------------------------------------------------------------- /Settings.Panels/ControlAliases.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Settings.Panels 2 | { 3 | partial class ControlAliases 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.textBoxAliases = new System.Windows.Forms.TextBox(); 32 | this.SuspendLayout(); 33 | // 34 | // textBoxAliases 35 | // 36 | this.textBoxAliases.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.textBoxAliases.Font = new System.Drawing.Font("Bitstream Vera Sans Mono", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 38 | this.textBoxAliases.Location = new System.Drawing.Point(0, 0); 39 | this.textBoxAliases.Multiline = true; 40 | this.textBoxAliases.Name = "textBoxAliases"; 41 | this.textBoxAliases.Size = new System.Drawing.Size(300, 300); 42 | this.textBoxAliases.TabIndex = 0; 43 | // 44 | // ControlAliases 45 | // 46 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 48 | this.Controls.Add(this.textBoxAliases); 49 | this.Name = "ControlAliases"; 50 | this.Size = new System.Drawing.Size(300, 300); 51 | this.ResumeLayout(false); 52 | this.PerformLayout(); 53 | 54 | } 55 | 56 | #endregion 57 | 58 | private System.Windows.Forms.TextBox textBoxAliases; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Settings.Panels/ControlAliases.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows.Forms; 4 | 5 | namespace GitForce.Settings.Panels 6 | { 7 | public partial class ControlAliases : UserControl, IUserSettings 8 | { 9 | public ControlAliases() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | /// 15 | /// Initialize pertinent settings 16 | /// 17 | /// All git global settings 18 | public void Init(string[] options) 19 | { 20 | foreach (string s in options) 21 | { 22 | // Populate text box with aliases... 23 | try 24 | { 25 | string[] def = s.Split('\n'); // Definition 26 | string[] sec = def[0].Split('.'); // Section 27 | 28 | switch (sec[0]) 29 | { 30 | case "alias": 31 | textBoxAliases.Text += sec[1] + "=" + def[1] + Environment.NewLine; 32 | break; 33 | } 34 | } 35 | catch (Exception ex) 36 | { 37 | App.PrintLogMessage(ex.Message, MessageType.Error); 38 | } 39 | } 40 | 41 | // Add the dirty (modified) value changed helper 42 | textBoxAliases.TextChanged += ControlDirtyHelper.ControlDirty; 43 | } 44 | 45 | /// 46 | /// Control received a focus (true) or lost a focus (false) 47 | /// 48 | public void Focus(bool focused) 49 | { 50 | } 51 | 52 | /// 53 | /// Apply changed settings 54 | /// 55 | public void ApplyChanges() 56 | { 57 | if (textBoxAliases.Tag != null) 58 | { 59 | // Remove all aliases and then rebuild them 60 | if (ClassGit.Run("config --remove-section alias").Success() == false) 61 | App.PrintLogMessage("ClassAliases: Error removing section aliases", MessageType.Error); 62 | 63 | foreach (string[] def in 64 | textBoxAliases.Lines.Select(s => s.Trim().Split('=')).Where(def => def.Length == 2)) 65 | { 66 | ClassConfig.SetGlobal("alias." + def[0].Trim(), def[1].Trim()); 67 | } 68 | 69 | textBoxAliases.Tag = null; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Settings.Panels/ControlCommits.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Settings.Panels 5 | { 6 | public partial class ControlCommits : UserControl, IUserSettings 7 | { 8 | public ControlCommits() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | /// 14 | /// Initialize pertinent settings 15 | /// 16 | /// All git global settings 17 | public void Init(string[] options) 18 | { 19 | numBoxLast.Value = Properties.Settings.Default.commitsRetrieveLast; 20 | rbRetrieveAll.Checked = Properties.Settings.Default.commitsRetrieveAll; 21 | rbRetrieveLast.Checked = !rbRetrieveAll.Checked; 22 | } 23 | 24 | /// 25 | /// Control received a focus (true) or lost a focus (false) 26 | /// 27 | public void Focus(bool focused) 28 | { 29 | } 30 | 31 | /// 32 | /// Apply changed settings 33 | /// 34 | public void ApplyChanges() 35 | { 36 | Properties.Settings.Default.commitsRetrieveLast = (int)numBoxLast.Value; 37 | Properties.Settings.Default.commitsRetrieveAll = rbRetrieveAll.Checked; 38 | } 39 | 40 | /// 41 | /// Retrieve number of changes radio button changed 42 | /// 43 | private void RbRetrieveAllCheckedChanged(object sender, EventArgs e) 44 | { 45 | numBoxLast.ReadOnly = rbRetrieveAll.Checked; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Settings.Panels/ControlDiff.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | 6 | namespace GitForce.Settings.Panels 7 | { 8 | public partial class ControlDiff : UserControl, IUserSettings 9 | { 10 | /// 11 | /// List of helper programs 12 | /// 13 | private List helpers; 14 | 15 | public ControlDiff() 16 | { 17 | InitializeComponent(); 18 | 19 | textDesc.Text = "A diff utility needs to support these arguments:" + Environment.NewLine + 20 | "%1 - Local file ($LOCAL)" + Environment.NewLine + 21 | "%2 - Remote file ($REMOTE)"; 22 | } 23 | 24 | /// 25 | /// Initialize pertinent settings 26 | /// 27 | /// All git global settings 28 | public void Init(string[] options) 29 | { 30 | // Detect all diff utilities on the system and populate a listbox 31 | helpers = ClassDiff.GetDetected(); 32 | comboBoxPath.Items.Clear(); 33 | foreach (var appHelper in helpers) 34 | comboBoxPath.Items.Add(appHelper.Path); 35 | 36 | // Get our program default diff tool and set the listbox text 37 | AppHelper app = new AppHelper(Properties.Settings.Default.DiffAppHelper); 38 | comboBoxPath.Text = app.Path; 39 | textArgs.Text = app.Args; 40 | 41 | // Add the dirty (modified) value changed helper 42 | comboBoxPath.TextChanged += ControlDirtyHelper.ControlDirty; 43 | textArgs.TextChanged += ControlDirtyHelper.ControlDirty; 44 | } 45 | 46 | /// 47 | /// Control received a focus (true) or lost a focus (false) 48 | /// 49 | public void Focus(bool focused) 50 | { 51 | } 52 | 53 | /// 54 | /// Apply changed settings 55 | /// 56 | public void ApplyChanges() 57 | { 58 | if (comboBoxPath.Tag != null || textArgs.Tag !=null) 59 | { 60 | try 61 | { 62 | string name = Path.GetFileNameWithoutExtension(comboBoxPath.Text.Trim()); 63 | AppHelper app = new AppHelper(name, comboBoxPath.Text, textArgs.Text.Trim()); 64 | Properties.Settings.Default.DiffAppHelper = app.ToString(); 65 | 66 | ClassDiff.Configure(app); 67 | } 68 | catch (Exception ex) 69 | { 70 | App.PrintLogMessage(ex.Message, MessageType.Error); 71 | } 72 | } 73 | } 74 | 75 | /// 76 | /// Browse for a utility using a file open dialog 77 | /// 78 | private void BtBrowseClick(object sender, EventArgs e) 79 | { 80 | if (openApp.ShowDialog() == DialogResult.OK) 81 | { 82 | comboBoxPath.Text = openApp.FileName; 83 | textArgs.Text = "%1 %2"; 84 | } 85 | } 86 | 87 | /// 88 | /// Item was selected from the drop-down list 89 | /// 90 | private void ComboBoxPathSelectionChangeCommitted(object sender, EventArgs e) 91 | { 92 | ComboBox senderComboBox = (ComboBox) sender; 93 | textArgs.Text = helpers[senderComboBox.SelectedIndex].Args; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Settings.Panels/ControlDoubleClick.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Windows.Forms; 4 | 5 | namespace GitForce.Settings.Panels 6 | { 7 | public partial class ControlDoubleClick : UserControl, IUserSettings 8 | { 9 | // Selected radio button option number 10 | private string option = Properties.Settings.Default.DoubleClick; 11 | 12 | public ControlDoubleClick() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | /// 18 | /// Initialize pertinent settings 19 | /// 20 | /// All git global settings 21 | public void Init(string[] options) 22 | { 23 | // Load a list of programs from the application settings 24 | string values = Properties.Settings.Default.EditViewPrograms; 25 | string[] progs = values.Split(("\0").ToCharArray(), StringSplitOptions.RemoveEmptyEntries); 26 | foreach (string s in progs) 27 | comboApps.Items.Add(s); 28 | comboApps.Text = Properties.Settings.Default.DoubleClickProgram; 29 | 30 | // Check the radio button with the currently stored action 31 | Dictionary rb = new Dictionary { 32 | { "0", radioButton0 }, { "1", radioButton1 }, { "2", radioButton2 } }; 33 | 34 | if (!rb.ContainsKey(option)) 35 | option = "1"; 36 | rb[option].Checked = true; 37 | comboApps.Enabled = option == "2"; 38 | } 39 | 40 | /// 41 | /// Control received a focus (true) or lost a focus (false) 42 | /// 43 | public void Focus(bool focused) 44 | { 45 | } 46 | 47 | /// 48 | /// Apply changed settings 49 | /// 50 | public void ApplyChanges() 51 | { 52 | Properties.Settings.Default.DoubleClickProgram = comboApps.Text; 53 | Properties.Settings.Default.DoubleClick = option; 54 | } 55 | 56 | /// 57 | /// Radio button clicked 58 | /// 59 | private void RadioButtonCheckedChanged(object sender, EventArgs e) 60 | { 61 | RadioButton rb = sender as RadioButton; 62 | if (rb.Checked) 63 | { 64 | option = rb.Tag.ToString(); 65 | comboApps.Enabled = rb.Tag.ToString() == "2"; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Settings.Panels/ControlFiles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Settings.Panels 5 | { 6 | public partial class ControlFiles : UserControl, IUserSettings 7 | { 8 | public ControlFiles() 9 | { 10 | InitializeComponent(); 11 | 12 | // Update visuals on dependent checkbox as described below 13 | CheckBoxRefreshOnChangeCheckedChanged(null, null); 14 | CheckBoxScanTabsCheckedChanged(null, null); 15 | } 16 | 17 | /// 18 | /// Initialize pertinent settings 19 | /// 20 | /// All git global settings 21 | public void Init(string[] options) 22 | { 23 | string value = ClassConfig.GetGlobal("core.ignorecase"); 24 | checkBoxIgnoreCase.Checked = (value.ToLower() == "true") ? true : false; 25 | checkBoxShowDotGit.Checked = Properties.Settings.Default.ShowDotGitFolders; 26 | checkBoxDeepScan.Checked = Properties.Settings.Default.RepoDeepScan; 27 | checkBoxRefreshOnChange.Checked = Properties.Settings.Default.RefreshOnChange; 28 | checkBoxReaddOnChange.Checked = Properties.Settings.Default.ReaddOnChange; 29 | checkBoxScanTabs.Checked = Properties.Settings.Default.WarnOnTabs; 30 | textBoxScanExt.Text = Properties.Settings.Default.WarnOnTabsExt; 31 | 32 | // Add the dirty (modified) value changed helper 33 | checkBoxIgnoreCase.CheckStateChanged += ControlDirtyHelper.ControlDirty; 34 | checkBoxRefreshOnChange.CheckStateChanged += ControlDirtyHelper.ControlDirty; 35 | checkBoxReaddOnChange.CheckStateChanged += ControlDirtyHelper.ControlDirty; 36 | checkBoxScanTabs.CheckStateChanged += ControlDirtyHelper.ControlDirty; 37 | textBoxScanExt.TextChanged += ControlDirtyHelper.ControlDirty; 38 | } 39 | 40 | /// 41 | /// Control received a focus (true) or lost a focus (false) 42 | /// 43 | public void Focus(bool focused) 44 | { 45 | } 46 | 47 | /// 48 | /// Apply changed settings 49 | /// 50 | public void ApplyChanges() 51 | { 52 | if (checkBoxIgnoreCase.Tag != null) 53 | { 54 | ClassConfig.SetGlobal("core.ignorecase", checkBoxIgnoreCase.Checked.ToString()); 55 | checkBoxIgnoreCase.Tag = null; 56 | } 57 | 58 | Properties.Settings.Default.ShowDotGitFolders = checkBoxShowDotGit.Checked; 59 | Properties.Settings.Default.RepoDeepScan = checkBoxDeepScan.Checked; 60 | Properties.Settings.Default.RefreshOnChange = checkBoxRefreshOnChange.Checked; 61 | Properties.Settings.Default.ReaddOnChange = checkBoxReaddOnChange.Checked; 62 | Properties.Settings.Default.WarnOnTabs = checkBoxScanTabs.Checked; 63 | Properties.Settings.Default.WarnOnTabsExt = textBoxScanExt.Text; 64 | 65 | // If the auto-refresh settings were changed, run the commits refresh to (de)arm the code 66 | if (checkBoxRefreshOnChange.Tag != null || checkBoxReaddOnChange.Tag != null) 67 | { 68 | App.MainForm.SelectiveRefresh(FormMain.SelectveRefreshFlags.Commits); 69 | checkBoxRefreshOnChange.Tag = checkBoxReaddOnChange.Tag = null; 70 | } 71 | } 72 | 73 | /// 74 | /// The option to re-add on change is dependent on refresh on change 75 | /// 76 | private void CheckBoxRefreshOnChangeCheckedChanged(object sender, EventArgs e) 77 | { 78 | checkBoxReaddOnChange.Enabled = checkBoxRefreshOnChange.Checked; 79 | } 80 | 81 | /// 82 | /// The edit text field to specify which files to check is dependent on the warn on tabs checkbox change 83 | /// 84 | private void CheckBoxScanTabsCheckedChanged(object sender, EventArgs e) 85 | { 86 | textBoxScanExt.Enabled = checkBoxScanTabs.Checked; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Settings.Panels/ControlGitconfig.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Settings.Panels 2 | { 3 | partial class ControlGitconfig 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.userControlEditFile = new GitForce.UserControlEditFile(); 32 | this.SuspendLayout(); 33 | // 34 | // userControlEditFile 35 | // 36 | this.userControlEditFile.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.userControlEditFile.Location = new System.Drawing.Point(0, 0); 38 | this.userControlEditFile.Name = "userControlEditFile"; 39 | this.userControlEditFile.Size = new System.Drawing.Size(300, 300); 40 | this.userControlEditFile.TabIndex = 0; 41 | // 42 | // ControlGitconfig 43 | // 44 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 45 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 46 | this.Controls.Add(this.userControlEditFile); 47 | this.Name = "ControlGitconfig"; 48 | this.Size = new System.Drawing.Size(300, 300); 49 | this.ResumeLayout(false); 50 | 51 | } 52 | 53 | #endregion 54 | 55 | private UserControlEditFile userControlEditFile; 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Settings.Panels/ControlGitconfig.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Settings.Panels 5 | { 6 | public partial class ControlGitconfig : UserControl, IUserSettings 7 | { 8 | /// 9 | /// File containing user gitconfig settings 10 | /// 11 | private string configFile; 12 | 13 | public ControlGitconfig() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | /// 19 | /// Initialize pertinent settings 20 | /// 21 | /// All git global settings 22 | public void Init(string[] options) 23 | { 24 | configFile = Path.Combine(App.UserHome, ".gitconfig"); 25 | } 26 | 27 | /// 28 | /// Control received a focus (true) or lost a focus (false) 29 | /// 30 | public void Focus(bool focused) 31 | { 32 | if (focused) 33 | userControlEditFile.LoadFile(configFile); 34 | else 35 | { 36 | // As the control is losing its focus, if the text was changed, ask the user 37 | // to save the changes or not. This behavior is a special case since we need 38 | // to make changes to this config file atomic. 39 | if (userControlEditFile.Dirty) 40 | { 41 | if (MessageBox.Show("Save changes to the configuration file?", "Edit .gitconfig", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) 42 | userControlEditFile.SaveFile(configFile); 43 | else 44 | userControlEditFile.LoadFile(configFile); 45 | } 46 | } 47 | } 48 | 49 | /// 50 | /// Apply changed settings 51 | /// 52 | public void ApplyChanges() 53 | { 54 | if (userControlEditFile.Dirty) 55 | userControlEditFile.SaveFile(configFile); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Settings.Panels/ControlGitignore.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Settings.Panels 2 | { 3 | partial class ControlGitignore 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.userControlEditGitignore = new UserControlEditGitignore(); 32 | this.SuspendLayout(); 33 | // 34 | // userControlEditGitignore 35 | // 36 | this.userControlEditGitignore.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.userControlEditGitignore.Location = new System.Drawing.Point(0, 0); 38 | this.userControlEditGitignore.Name = "userControlEditGitignore"; 39 | this.userControlEditGitignore.Size = new System.Drawing.Size(300, 300); 40 | this.userControlEditGitignore.TabIndex = 0; 41 | // 42 | // ControlGitignore 43 | // 44 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 45 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 46 | this.Controls.Add(this.userControlEditGitignore); 47 | this.Name = "ControlGitignore"; 48 | this.Size = new System.Drawing.Size(300, 300); 49 | this.ResumeLayout(false); 50 | 51 | } 52 | 53 | #endregion 54 | 55 | private UserControlEditGitignore userControlEditGitignore; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Settings.Panels/ControlGitignore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace GitForce.Settings.Panels 7 | { 8 | public partial class ControlGitignore : UserControl, IUserSettings 9 | { 10 | /// 11 | /// File containing user gitignore settings 12 | /// 13 | private string excludesFile; 14 | 15 | public ControlGitignore() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | /// 21 | /// Initialize pertinent settings 22 | /// 23 | /// All git global settings 24 | public void Init(string[] options) 25 | { 26 | // Get a path to user excludes file, or create that file if it is not defined 27 | excludesFile = options.FirstOrDefault(s => s.Contains("core.excludesfile")); 28 | 29 | // If the file does not exist, reset it 30 | if (excludesFile == null) 31 | excludesFile = Path.Combine(App.AppHome, ".gitexcludesfile"); 32 | 33 | excludesFile = excludesFile.Split('\n').Last(); 34 | 35 | if (!File.Exists(excludesFile)) 36 | try 37 | { 38 | File.CreateText(excludesFile).Close(); 39 | } 40 | catch (Exception ex) 41 | { 42 | App.PrintStatusMessage("Error loading " + excludesFile + ": " + ex.Message, MessageType.Error); 43 | } 44 | 45 | userControlEditGitignore.LoadGitIgnore(excludesFile); 46 | } 47 | 48 | /// 49 | /// Control received a focus (true) or lost a focus (false) 50 | /// 51 | public void Focus(bool focused) 52 | { 53 | } 54 | 55 | /// 56 | /// Apply changed settings 57 | /// 58 | public void ApplyChanges() 59 | { 60 | userControlEditGitignore.SaveGitIgnore(excludesFile); 61 | ClassConfig.SetGlobal("core.excludesfile", excludesFile); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Settings.Panels/ControlGlobal.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce.Settings.Panels 4 | { 5 | public partial class ControlGlobal : UserControl, IUserSettings 6 | { 7 | public ControlGlobal() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | /// 13 | /// Keeps the global settings of line endings 14 | /// 15 | private string crlf; 16 | 17 | /// 18 | /// Initialize pertinent settings 19 | /// 20 | /// All git global settings 21 | public void Init(string[] options) 22 | { 23 | // Initialize the line endings radio buttons 24 | crlf = ClassConfig.GetGlobal("core.autocrlf"); 25 | if (crlf == "true") radio1.Checked = true; 26 | if (crlf == "input") radio2.Checked = true; 27 | if (crlf == "false") radio3.Checked = true; 28 | } 29 | 30 | /// 31 | /// Control received a focus (true) or lost a focus (false) 32 | /// 33 | public void Focus(bool focused) 34 | { 35 | } 36 | 37 | /// 38 | /// Apply changed settings 39 | /// 40 | public void ApplyChanges() 41 | { 42 | // Default core.autocrlf setting is "true" on Windows and "false" on Linux 43 | string newCrlf = ClassUtils.IsMono() ? "false" : "true"; 44 | if (radio1.Checked) newCrlf = "true"; 45 | if (radio2.Checked) newCrlf = "input"; 46 | if (radio3.Checked) newCrlf = "false"; 47 | 48 | if (newCrlf != crlf) 49 | ClassConfig.SetGlobal("core.autocrlf", newCrlf); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Settings.Panels/ControlMerge.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | 6 | namespace GitForce.Settings.Panels 7 | { 8 | public partial class ControlMerge : UserControl, IUserSettings 9 | { 10 | /// 11 | /// List of helper programs 12 | /// 13 | private List helpers; 14 | 15 | public ControlMerge() 16 | { 17 | InitializeComponent(); 18 | 19 | textDesc.Text = "A merge utility needs to support these arguments:" + Environment.NewLine + 20 | "%1 - Base file ($BASE)" + Environment.NewLine + 21 | "%2 - Local file ($LOCAL)" + Environment.NewLine + 22 | "%3 - Remote file ($REMOTE)" + Environment.NewLine + 23 | "%4 - Merged file ($MERGED)"; 24 | } 25 | 26 | /// 27 | /// Initialize pertinent settings 28 | /// 29 | /// All git global settings 30 | public void Init(string[] options) 31 | { 32 | // Detect all merge utilities on the system and populate a listbox 33 | helpers = ClassMerge.GetDetected(); 34 | comboBoxPath.Items.Clear(); 35 | foreach (var appHelper in helpers) 36 | comboBoxPath.Items.Add(appHelper.Path); 37 | 38 | // Get our program default merge tool and set the listbox text 39 | AppHelper app = new AppHelper(Properties.Settings.Default.MergeAppHelper); 40 | comboBoxPath.Text = app.Path; 41 | textArgs.Text = app.Args; 42 | 43 | // Add the dirty (modified) value changed helper 44 | comboBoxPath.TextChanged += ControlDirtyHelper.ControlDirty; 45 | textArgs.TextChanged += ControlDirtyHelper.ControlDirty; 46 | } 47 | 48 | /// 49 | /// Control received a focus (true) or lost a focus (false) 50 | /// 51 | public void Focus(bool focused) 52 | { 53 | } 54 | 55 | /// 56 | /// Apply changed settings 57 | /// 58 | public void ApplyChanges() 59 | { 60 | if (comboBoxPath.Tag != null || textArgs.Tag !=null) 61 | { 62 | try 63 | { 64 | string name = Path.GetFileNameWithoutExtension(comboBoxPath.Text.Trim()); 65 | AppHelper app = new AppHelper(name, comboBoxPath.Text, textArgs.Text.Trim()); 66 | Properties.Settings.Default.MergeAppHelper = app.ToString(); 67 | 68 | ClassMerge.Configure(app); 69 | } 70 | catch (Exception ex) 71 | { 72 | App.PrintLogMessage(ex.Message, MessageType.Error); 73 | } 74 | } 75 | } 76 | 77 | /// 78 | /// Browse for a utility using a file open dialog 79 | /// 80 | private void BtBrowseClick(object sender, EventArgs e) 81 | { 82 | if (openApp.ShowDialog() == DialogResult.OK) 83 | { 84 | comboBoxPath.Text = openApp.FileName; 85 | textArgs.Text = "%1 %2 %3 %4"; 86 | } 87 | } 88 | 89 | /// 90 | /// Item was selected from the drop-down list 91 | /// 92 | private void ComboBoxPathSelectionChangeCommitted(object sender, EventArgs e) 93 | { 94 | ComboBox senderComboBox = (ComboBox) sender; 95 | textArgs.Text = helpers[senderComboBox.SelectedIndex].Args; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Settings.Panels/ControlOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce.Settings.Panels 4 | { 5 | public partial class ControlOptions : UserControl, IUserSettings 6 | { 7 | public ControlOptions() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | /// 13 | /// Initialize pertinent settings 14 | /// 15 | /// All git global settings 16 | public void Init(string[] options) 17 | { 18 | checkBoxTabs.Checked = Properties.Settings.Default.ShowTabsOnRightPane; 19 | checkBoxWarnMultipleInstances.Checked = Properties.Settings.Default.WarnMultipleInstances; 20 | checkBoxWarnIfAdmin.Checked = Properties.Settings.Default.WarnIfAdmin; 21 | checkBoxAutoCloseGitOnSuccess.Checked = Properties.Settings.Default.AutoCloseGitOnSuccess; 22 | 23 | // Add the dirty (modified) value changed helper 24 | checkBoxTabs.CheckStateChanged += ControlDirtyHelper.ControlDirty; 25 | } 26 | 27 | /// 28 | /// Control received a focus (true) or lost a focus (false) 29 | /// 30 | public void Focus(bool focused) 31 | { 32 | } 33 | 34 | /// 35 | /// Apply changed settings 36 | /// 37 | public void ApplyChanges() 38 | { 39 | Properties.Settings.Default.ShowTabsOnRightPane = checkBoxTabs.Checked; 40 | Properties.Settings.Default.WarnMultipleInstances = checkBoxWarnMultipleInstances.Checked; 41 | Properties.Settings.Default.WarnIfAdmin = checkBoxWarnIfAdmin.Checked; 42 | Properties.Settings.Default.AutoCloseGitOnSuccess = checkBoxAutoCloseGitOnSuccess.Checked; 43 | 44 | if (checkBoxTabs.Tag != null) 45 | App.MainForm.UpdateRightPaneTabsShowState(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Settings.Panels/ControlSsl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Settings.Panels 5 | { 6 | public partial class ControlSsl : UserControl, IUserSettings 7 | { 8 | public ControlSsl() 9 | { 10 | InitializeComponent(); 11 | } 12 | 13 | /// 14 | /// Initialize pertinent settings 15 | /// 16 | /// All git global settings 17 | public void Init(string[] options) 18 | { 19 | checkBoxLeavePageant.Checked = Properties.Settings.Default.leavePageant; 20 | 21 | // Add the dirty (modified) value changed helper 22 | checkBoxLeavePageant.CheckStateChanged += ControlDirtyHelper.ControlDirty; 23 | 24 | // Disable this tab on Linux 25 | if (ClassUtils.IsMono()) 26 | Enabled = false; 27 | } 28 | 29 | /// 30 | /// Control received a focus (true) or lost a focus (false) 31 | /// 32 | public void Focus(bool focused) 33 | { 34 | } 35 | 36 | /// 37 | /// Apply changed settings 38 | /// 39 | public void ApplyChanges() 40 | { 41 | Properties.Settings.Default.leavePageant = checkBoxLeavePageant.Checked; 42 | } 43 | 44 | /// 45 | /// Open the dialog to manage SSH keys 46 | /// 47 | private void btSshClick(object sender, EventArgs e) 48 | { 49 | FormSSH formSsh = new FormSSH(); 50 | formSsh.ShowDialog(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Settings.Panels/ControlStatus.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce.Settings.Panels 2 | { 3 | partial class ControlStatus 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.checkBoxShowGitCommands = new System.Windows.Forms.CheckBox(); 32 | this.checkBoxShowTimestamp = new System.Windows.Forms.CheckBox(); 33 | this.checkBoxUse24HourClock = new System.Windows.Forms.CheckBox(); 34 | this.SuspendLayout(); 35 | // 36 | // checkBoxShowGitCommands 37 | // 38 | this.checkBoxShowGitCommands.AutoSize = true; 39 | this.checkBoxShowGitCommands.Location = new System.Drawing.Point(3, 3); 40 | this.checkBoxShowGitCommands.Name = "checkBoxShowGitCommands"; 41 | this.checkBoxShowGitCommands.Size = new System.Drawing.Size(208, 17); 42 | this.checkBoxShowGitCommands.TabIndex = 0; 43 | this.checkBoxShowGitCommands.Text = "Show git commands in the status pane"; 44 | this.checkBoxShowGitCommands.UseVisualStyleBackColor = true; 45 | // 46 | // checkBoxShowTimestamp 47 | // 48 | this.checkBoxShowTimestamp.AutoSize = true; 49 | this.checkBoxShowTimestamp.Location = new System.Drawing.Point(3, 26); 50 | this.checkBoxShowTimestamp.Name = "checkBoxShowTimestamp"; 51 | this.checkBoxShowTimestamp.Size = new System.Drawing.Size(199, 17); 52 | this.checkBoxShowTimestamp.TabIndex = 1; 53 | this.checkBoxShowTimestamp.Text = "Show timestamp for status messages"; 54 | this.checkBoxShowTimestamp.UseVisualStyleBackColor = true; 55 | this.checkBoxShowTimestamp.CheckedChanged += new System.EventHandler(this.CheckBoxShowTimestampCheckedChanged); 56 | // 57 | // checkBoxUse24HourClock 58 | // 59 | this.checkBoxUse24HourClock.AutoSize = true; 60 | this.checkBoxUse24HourClock.Location = new System.Drawing.Point(30, 49); 61 | this.checkBoxUse24HourClock.Name = "checkBoxUse24HourClock"; 62 | this.checkBoxUse24HourClock.Size = new System.Drawing.Size(113, 17); 63 | this.checkBoxUse24HourClock.TabIndex = 2; 64 | this.checkBoxUse24HourClock.Text = "Use 24 hour clock"; 65 | this.checkBoxUse24HourClock.UseVisualStyleBackColor = true; 66 | // 67 | // ControlStatus 68 | // 69 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 70 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 71 | this.Controls.Add(this.checkBoxUse24HourClock); 72 | this.Controls.Add(this.checkBoxShowTimestamp); 73 | this.Controls.Add(this.checkBoxShowGitCommands); 74 | this.Name = "ControlStatus"; 75 | this.Size = new System.Drawing.Size(300, 300); 76 | this.ResumeLayout(false); 77 | this.PerformLayout(); 78 | 79 | } 80 | 81 | #endregion 82 | 83 | private System.Windows.Forms.CheckBox checkBoxShowGitCommands; 84 | private System.Windows.Forms.CheckBox checkBoxShowTimestamp; 85 | private System.Windows.Forms.CheckBox checkBoxUse24HourClock; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Settings.Panels/ControlStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace GitForce.Settings.Panels 5 | { 6 | public partial class ControlStatus : UserControl, IUserSettings 7 | { 8 | public ControlStatus() 9 | { 10 | InitializeComponent(); 11 | 12 | // Update visuals on dependent checkbox as described below 13 | CheckBoxShowTimestampCheckedChanged(null, null); 14 | } 15 | 16 | /// 17 | /// Initialize pertinent settings 18 | /// 19 | /// All git global settings 20 | public void Init(string[] options) 21 | { 22 | checkBoxShowGitCommands.Checked = Properties.Settings.Default.logCommands; 23 | checkBoxShowTimestamp.Checked = Properties.Settings.Default.logTime; 24 | checkBoxUse24HourClock.Checked = Properties.Settings.Default.logTime24; 25 | } 26 | 27 | /// 28 | /// Control received a focus (true) or lost a focus (false) 29 | /// 30 | public void Focus(bool focused) 31 | { 32 | } 33 | 34 | /// 35 | /// Apply changed settings 36 | /// 37 | public void ApplyChanges() 38 | { 39 | Properties.Settings.Default.logCommands = checkBoxShowGitCommands.Checked; 40 | Properties.Settings.Default.logTime = checkBoxShowTimestamp.Checked; 41 | Properties.Settings.Default.logTime24 = checkBoxUse24HourClock.Checked; 42 | } 43 | 44 | /// 45 | /// The option to use 24-hour clock is dependent on showing the timestamp 46 | /// 47 | private void CheckBoxShowTimestampCheckedChanged(object sender, EventArgs e) 48 | { 49 | checkBoxUse24HourClock.Enabled = checkBoxShowTimestamp.Checked; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Settings.Panels/ControlUser.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace GitForce.Settings.Panels 4 | { 5 | public partial class ControlUser : UserControl, IUserSettings 6 | { 7 | public ControlUser() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | /// 13 | /// Initialize pertinent settings 14 | /// 15 | /// All git global settings 16 | public void Init(string[] options) 17 | { 18 | textBoxUserName.Text = ClassConfig.GetGlobal("user.name"); 19 | textBoxUserEmail.Text = ClassConfig.GetGlobal("user.email"); 20 | 21 | // Add the dirty (modified) value changed helper 22 | textBoxUserName.TextChanged += ControlDirtyHelper.ControlDirty; 23 | textBoxUserEmail.TextChanged += ControlDirtyHelper.ControlDirty; 24 | } 25 | 26 | /// 27 | /// Control received a focus (true) or lost a focus (false) 28 | /// 29 | public void Focus(bool focused) 30 | { 31 | } 32 | 33 | /// 34 | /// Apply changed settings 35 | /// 36 | public void ApplyChanges() 37 | { 38 | if (textBoxUserName.Tag != null) 39 | { 40 | ClassConfig.SetGlobal("user.name", textBoxUserName.Text.Trim()); 41 | textBoxUserName.Tag = null; 42 | } 43 | 44 | if (textBoxUserEmail.Tag != null) 45 | { 46 | ClassConfig.SetGlobal("user.email", textBoxUserEmail.Text.Trim()); 47 | textBoxUserEmail.Tag = null; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Settings.Panels/ControlViewEdit.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.Settings.Panels 8 | { 9 | public partial class ControlViewEdit : UserControl, IUserSettings 10 | { 11 | public ControlViewEdit() 12 | { 13 | InitializeComponent(); 14 | } 15 | 16 | /// 17 | /// If the list of editors is empty, find several common Windows or Linux editors 18 | /// and add them to the list. This is a static function called on program startup. 19 | /// 20 | public static void AddKnownEditors() 21 | { 22 | if (String.IsNullOrEmpty(Properties.Settings.Default.EditViewPrograms)) 23 | { 24 | List candidates = new List 25 | { 26 | // Windows OS common editors: 27 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), @"notepad.exe"), 28 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Windows NT\Accessories\wordpad.exe"), 29 | 30 | // Linux OS common GUI editors: 31 | @"/usr/bin/gedit", 32 | @"/usr/bin/emacs", 33 | }; 34 | 35 | // Add to the list all editors that can be accessed 36 | List editors = candidates.Where(File.Exists).ToList(); 37 | 38 | // Save the list of editors in settings 39 | if (editors.Count > 0) 40 | Properties.Settings.Default.EditViewPrograms = String.Join("\0", editors.ToArray()); 41 | } 42 | } 43 | 44 | /// 45 | /// Initialize pertinent settings 46 | /// 47 | /// All git global settings 48 | public void Init(string[] options) 49 | { 50 | // Load a list of programs from the application settings 51 | string values = Properties.Settings.Default.EditViewPrograms; 52 | string[] progs = values.Split(("\0").ToCharArray(), StringSplitOptions.RemoveEmptyEntries); 53 | foreach (string s in progs) 54 | listPrograms.Items.Add(s); 55 | } 56 | 57 | /// 58 | /// Control received a focus (true) or lost a focus (false) 59 | /// 60 | public void Focus(bool focused) 61 | { 62 | } 63 | 64 | /// 65 | /// Apply changed settings 66 | /// 67 | public void ApplyChanges() 68 | { 69 | // Store a list of programs to application settings 70 | List progs = listPrograms.Items.Cast().ToList(); 71 | Properties.Settings.Default.EditViewPrograms = String.Join("\0", progs.ToArray()); 72 | } 73 | 74 | /// 75 | /// User clicked on Add button to add a program 76 | /// 77 | private void BtAddClick(object sender, EventArgs e) 78 | { 79 | if (openFileDialog.ShowDialog() == DialogResult.OK) 80 | if (!listPrograms.Items.Contains(openFileDialog.FileName)) 81 | listPrograms.Items.Add(openFileDialog.FileName); 82 | } 83 | 84 | /// 85 | /// User clicked on Remove button to remove selected programs 86 | /// 87 | private void BtRemoveClick(object sender, EventArgs e) 88 | { 89 | while (listPrograms.SelectedItems.Count > 0) 90 | listPrograms.Items.Remove(listPrograms.SelectedItem); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /TabEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Windows.Forms; 4 | 5 | namespace GitForce 6 | { 7 | /// 8 | /// Extension to the standard Tab control giving us a method of hiding 9 | /// the tab control bar. 10 | /// 11 | public class TabEx : TabControl 12 | { 13 | [Category("Appearance")] 14 | [Description("Shows or hides the tab control")] 15 | [DefaultValue(typeof(bool),"false")] 16 | public bool ShowTabs { get; set; } 17 | 18 | public void UpdateTabState() 19 | { 20 | // We change this property to make tab redraw itself and show/hide 21 | // its tab control bar. That means we can only use Normal property for now. 22 | Appearance = ShowTabs ? TabAppearance.Normal : TabAppearance.FlatButtons; 23 | } 24 | 25 | protected override void WndProc(ref Message m) 26 | { 27 | // In design mode, show the tabs 28 | if (DesignMode) 29 | base.WndProc(ref m); 30 | else 31 | { 32 | // Hide the tabs if the message is TCM_ADJUSTRECT 33 | // and our control variable ShowTabs is false 34 | if (m.Msg == NativeMethods.TCM_ADJUSTRECT && !ShowTabs) 35 | m.Result = (IntPtr)1; 36 | else 37 | base.WndProc(ref m); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TextBoxEx.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | namespace GitForce 7 | { 8 | /// 9 | /// This is a fancy text box which is used by the direct command line box. 10 | /// 11 | /// The callback it implements, TextReady(), will trigger when the user 12 | /// presses Enter in the box. It will be called only when there is a non-empty 13 | /// text in the box (user does not have to check for empty text.) 14 | /// Also, text will be trimmed at the front and back from extra spaces. 15 | /// 16 | /// The text box will clear itself after the TextReady() has been sent. 17 | /// 18 | public class TextBoxEx : TextBox 19 | { 20 | public delegate void TextReadyEventHandler(object sender, string text); 21 | 22 | // Declare an event to trigger on Enter key 23 | [Category("Action")] 24 | [Description("Occurs when the text is ready for consumption")] 25 | public event TextReadyEventHandler TextReady; 26 | 27 | // List of strings entered so far to hold the history of input 28 | // Each string is unique 29 | private readonly List history = new List(); 30 | // Index into history when browsing it (Up / Down) 31 | private int iH; 32 | 33 | // Handler called on every key press into the subclassed TextBox 34 | // Using this handler we capture cursor up and down keys 35 | protected override void OnKeyDown(KeyEventArgs e) 36 | { 37 | switch (e.KeyCode) 38 | { 39 | // Up suggests a history entry 40 | case Keys.Up: 41 | if (iH > 0) 42 | { 43 | iH--; 44 | Text = history[iH]; 45 | Select(Text.Length, 0); 46 | } 47 | e.Handled = true; 48 | break; 49 | 50 | // Down suggests a history entry 51 | case Keys.Down: 52 | if (iH < history.Count-1) 53 | { 54 | iH++; 55 | Text = history[iH]; 56 | Select(Text.Length, 0); 57 | } 58 | e.Handled = true; 59 | break; 60 | } 61 | base.OnKeyDown(e); 62 | } 63 | 64 | // Handler called on every key press into the subclassed TextBox 65 | // Using this handler we capture ASCII keys 66 | protected override void OnKeyPress(KeyPressEventArgs e) 67 | { 68 | switch (e.KeyChar) 69 | { 70 | // On Enter, process the buffer and send a method 71 | case (char)Keys.Enter: 72 | // Trim the line from the extra spaces at both ends 73 | Text = Text.Trim(); 74 | 75 | // Send a message that the text is ready (if there is any text available) 76 | if (TextReady != null && Text.Length > 0) 77 | TextReady(this, Text); 78 | 79 | if (Text.Length > 0 && !history.Contains(Text)) 80 | history.Add(Text); 81 | 82 | iH = history.Count(); 83 | Text = string.Empty; 84 | 85 | e.Handled = true; 86 | break; 87 | 88 | // ESC clears the text box entry 89 | case (char)Keys.Escape: 90 | Text = string.Empty; 91 | e.Handled = true; // This also avoids the chime 92 | break; 93 | } 94 | base.OnKeyPress(e); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /UserControlEditFile.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace GitForce 2 | { 3 | partial class UserControlEditFile 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.labelFileName = new System.Windows.Forms.Label(); 32 | this.textBox = new System.Windows.Forms.TextBox(); 33 | this.SuspendLayout(); 34 | // 35 | // labelFileName 36 | // 37 | this.labelFileName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 38 | | System.Windows.Forms.AnchorStyles.Right))); 39 | this.labelFileName.Location = new System.Drawing.Point(0, 0); 40 | this.labelFileName.Name = "labelFileName"; 41 | this.labelFileName.Size = new System.Drawing.Size(356, 19); 42 | this.labelFileName.TabIndex = 0; 43 | this.labelFileName.Text = "File:"; 44 | // 45 | // textBox 46 | // 47 | this.textBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 48 | | System.Windows.Forms.AnchorStyles.Left) 49 | | System.Windows.Forms.AnchorStyles.Right))); 50 | this.textBox.Font = new System.Drawing.Font("Bitstream Vera Sans Mono", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 51 | this.textBox.Location = new System.Drawing.Point(3, 22); 52 | this.textBox.Multiline = true; 53 | this.textBox.Name = "textBox"; 54 | this.textBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; 55 | this.textBox.Size = new System.Drawing.Size(350, 173); 56 | this.textBox.TabIndex = 1; 57 | this.textBox.WordWrap = false; 58 | this.textBox.TextChanged += new System.EventHandler(this.TextBoxTextChanged); 59 | // 60 | // UserControlEditFile 61 | // 62 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 63 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 64 | this.Controls.Add(this.textBox); 65 | this.Controls.Add(this.labelFileName); 66 | this.Name = "UserControlEditFile"; 67 | this.Size = new System.Drawing.Size(356, 198); 68 | this.ResumeLayout(false); 69 | this.PerformLayout(); 70 | 71 | } 72 | 73 | #endregion 74 | 75 | private System.Windows.Forms.Label labelFileName; 76 | private System.Windows.Forms.TextBox textBox; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /UserControlEditFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Windows.Forms; 4 | 5 | namespace GitForce 6 | { 7 | public partial class UserControlEditFile : UserControl 8 | { 9 | /// 10 | /// True if the content of a text box is modified. 11 | /// 12 | public bool Dirty; 13 | 14 | public UserControlEditFile() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | /// 20 | /// Loads specified text file to edit 21 | /// 22 | public bool LoadFile(string file) 23 | { 24 | bool result = true; 25 | labelFileName.Text = file; 26 | textBox.Text = ""; 27 | try 28 | { 29 | using (StreamReader sr = new StreamReader(file)) 30 | { 31 | while (!sr.EndOfStream) 32 | { 33 | textBox.Text += sr.ReadLine() + Environment.NewLine; 34 | } 35 | } 36 | } 37 | catch (Exception) 38 | { 39 | textBox.Text = "(Unable to load file)"; 40 | result = false; 41 | } 42 | Dirty = false; 43 | textBox.Enabled = result; 44 | return result; 45 | } 46 | 47 | /// 48 | /// Saves the edited content of the text box into a file 49 | /// 50 | public bool SaveFile(string file) 51 | { 52 | // Dont attempt to save non-loaded content 53 | if (textBox.Enabled == false) 54 | return false; 55 | 56 | bool result = true; 57 | try 58 | { 59 | using (StreamWriter sw = new StreamWriter(file)) 60 | sw.WriteLine(textBox.Text); 61 | labelFileName.Text = file; 62 | Dirty = false; 63 | } 64 | catch (Exception ex) 65 | { 66 | MessageBox.Show(ex.Message, "Edit file", MessageBoxButtons.OK, MessageBoxIcon.Error); 67 | result = false; 68 | } 69 | return result; 70 | } 71 | 72 | /// 73 | /// User modified the content of a text box. Mark it as dirty. 74 | /// 75 | private void TextBoxTextChanged(object sender, EventArgs e) 76 | { 77 | Dirty = true; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /UserControlEditGitignore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | 7 | namespace GitForce 8 | { 9 | public partial class UserControlEditGitignore : UserControl 10 | { 11 | /// 12 | /// Current file name, displayed on the control 13 | /// 14 | private string FileName 15 | { 16 | set 17 | { 18 | labelFileName.Text = value; 19 | } 20 | } 21 | 22 | public UserControlEditGitignore() 23 | { 24 | InitializeComponent(); 25 | } 26 | 27 | /// 28 | /// Loads specified text file as a gitignore file 29 | /// 30 | public bool LoadGitIgnore(string file) 31 | { 32 | bool result = true; 33 | try 34 | { 35 | using (StreamReader sr = new StreamReader(file)) 36 | { 37 | // Read a configuration file which may use Windows or Unix specific newline code: 38 | // CR = 0D \r 39 | // LF = 0A \n 40 | // Windows OS uses CR LF, Unix OS uses LF only 41 | string content = sr.ReadToEnd(); 42 | content = content.Replace("\r", String.Empty); // Remove 0D (\r) character 43 | content = content.Replace("\n", Environment.NewLine); // Make sure we use OS-specific newline 44 | textBox.Text = content; 45 | } 46 | FileName = file; 47 | } 48 | catch (Exception ex) 49 | { 50 | MessageBox.Show(ex.Message, "Edit gitignore", MessageBoxButtons.OK, MessageBoxIcon.Error); 51 | result = false; 52 | } 53 | return result; 54 | } 55 | 56 | /// 57 | /// Saves the edited content of a gitignore listbox into a file 58 | /// 59 | public bool SaveGitIgnore(string file) 60 | { 61 | bool result = true; 62 | try 63 | { 64 | using (StreamWriter sw = new StreamWriter(file)) 65 | { 66 | // Write the content of the text box while trimming each line and ignoring empty ones 67 | for (int i = 0; i < textBox.Lines.Length; i++) 68 | { 69 | if (textBox.Lines[i].Trim().Length > 0) 70 | sw.WriteLine(textBox.Lines[i].Trim()); 71 | } 72 | } 73 | FileName = file; 74 | } 75 | catch (Exception ex) 76 | { 77 | MessageBox.Show(ex.Message, "Edit gitignore", MessageBoxButtons.OK, MessageBoxIcon.Error); 78 | result = false; 79 | } 80 | return result; 81 | } 82 | 83 | /// 84 | /// Add all selected items to the gitignore text box 85 | /// Dont add duplicates. 86 | /// 87 | private void BtAddClick(object sender, EventArgs e) 88 | { 89 | List items = (from string s in listFilters.SelectedItems select s.Split(' ').First()).ToList(); 90 | items.InsertRange(0, textBox.Lines); 91 | textBox.Lines = items.Distinct().ToArray(); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /git.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdevic/GitForce/38707f3f530bfe9cab9c6a37a9920652e3f62bb4/git.ico --------------------------------------------------------------------------------