1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2014 - TortoiseGit
4 // Copyright (C) 2012 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "CloneCommand.h"
23 #include "GitProgressDlg.h"
24 #include "StringUtils.h"
26 #include "MessageBox.h"
29 #include "ProgressDlg.h"
31 #include "UnicodeUtils.h"
32 #include "SysProgressDlg.h"
34 static CString
GetExistingDirectoryForClone(CString path
)
36 if (PathFileExists(path
))
38 int index
= path
.ReverseFind('\\');
39 while (index
>= 0 && path
.GetLength() >= 3)
41 if (PathFileExists(path
.Left(index
)))
42 return path
.Left(index
);
43 path
= path
.Left(index
);
44 index
= path
.ReverseFind('\\');
50 bool CloneCommand::Execute()
52 CTGitPath cloneDirectory
;
53 if (!parser
.HasKey(_T("hasurlhandler")))
55 if (orgCmdLinePath
.IsEmpty())
57 cloneDirectory
.SetFromWin(sOrigCWD
, true);
58 DWORD len
= ::GetTempPath(0, NULL
);
59 std::unique_ptr
<TCHAR
[]> tszPath(new TCHAR
[len
]);
60 ::GetTempPath(len
, tszPath
.get());
61 if (_tcsncicmp(cloneDirectory
.GetWinPath(), tszPath
.get(), len
-2 /* \\ and \0 */) == 0)
63 // if the current directory is set to a temp directory,
64 // we don't use that but leave it empty instead.
65 cloneDirectory
.Reset();
69 cloneDirectory
= orgCmdLinePath
;
73 dlg
.m_Directory
= cloneDirectory
.GetWinPathString();
75 if (parser
.HasKey(_T("url")))
76 dlg
.m_URL
= parser
.GetVal(_T("url"));
77 if (parser
.HasKey(_T("exactpath")))
78 dlg
.m_bExactPath
= TRUE
;
80 if(dlg
.DoModal()==IDOK
)
84 recursiveStr
= _T("--recursive");
86 recursiveStr
= _T("");
90 bareStr
= _T("--bare");
94 CString nocheckoutStr
;
95 if (dlg
.m_bNoCheckout
)
96 nocheckoutStr
= _T("--no-checkout");
100 branchStr
= _T("--branch ") + dlg
.m_strBranch
;
104 originStr
= _T("--origin ") + dlg
.m_strOrigin
;
106 if(dlg
.m_bAutoloadPuttyKeyFile
)
108 CAppUtils::LaunchPAgent(&dlg
.m_strPuttyKeyFile
);
111 CAppUtils::RemoveTrailSlash(dlg
.m_Directory
);
113 CAppUtils::RemoveTrailSlash(dlg
.m_URL
);
115 CString dir
=dlg
.m_Directory
;
116 CString url
=dlg
.m_URL
;
118 // is this a windows format UNC path, ie starts with \\?
119 if (url
.Find(_T("\\\\")) == 0)
121 // yes, change all \ to /
122 // this should not be necessary but msysgit does not support the use \ here yet
123 int atSign
= url
.Find(_T('@'));
126 CString path
= url
.Mid(atSign
);
127 path
.Replace(_T('\\'), _T('/'));
128 url
= url
.Mid(0, atSign
) + path
;
131 url
.Replace( _T('\\'), _T('/'));
137 depth
.Format(_T(" --depth %d"),dlg
.m_nDepth
);
140 g_Git
.m_CurrentDir
= GetExistingDirectoryForClone(dlg
.m_Directory
);
145 int ver
= CAppUtils::GetMsysgitVersion();
147 if(ver
>= 0x01070002) //above 1.7.0.2
148 progressarg
= _T("--progress");
150 cmd
.Format(_T("git.exe clone %s %s %s %s %s %s -v %s \"%s\" \"%s\""),
161 // Handle Git SVN-clone
164 //g_Git.m_CurrentDir=dlg.m_Directory;
165 cmd
.Format(_T("git.exe svn clone \"%s\" \"%s\""),
166 url
,dlg
.m_Directory
);
169 cmd
+=_T(" -T ")+dlg
.m_strSVNTrunk
;
172 cmd
+=_T(" -b ")+dlg
.m_strSVNBranchs
;
175 cmd
+=_T(" -t ")+dlg
.m_strSVNTags
;
180 str
.Format(_T("%d:HEAD"),dlg
.m_nSVNFrom
);
184 if(dlg
.m_bSVNUserName
)
186 cmd
+= _T(" --username ");
187 cmd
+=dlg
.m_strUserName
;
192 if (g_Git
.UsingLibGit2(CGit::GIT_CMD_CLONE
))
194 CGitProgressDlg GitDlg
;
196 g_Git
.m_CurrentDir
= dir
;
197 list
.AddPath(CTGitPath(dir
));
198 GitDlg
.SetCommand(CGitProgressList::GitProgress_Clone
);
200 GitDlg
.SetPathList(list
);
201 GitDlg
.SetIsBare(!!dlg
.m_bBare
);
202 GitDlg
.SetRefSpec(dlg
.m_bBranch
? dlg
.m_strBranch
: CString());
203 GitDlg
.SetRemote(dlg
.m_bOrigin
? dlg
.m_strOrigin
: CString());
204 GitDlg
.SetNoCheckout(!!dlg
.m_bNoCheckout
);
206 return !GitDlg
.DidErrorsOccur();
209 CProgressDlg progress
;
210 progress
.m_GitCmd
=cmd
;
211 progress
.m_PostCmdList
.Add(CString(MAKEINTRESOURCE(IDS_MENULOG
)));
212 progress
.m_PostCmdList
.Add(CString(MAKEINTRESOURCE(IDS_STATUSLIST_CONTEXT_EXPLORE
)));
213 INT_PTR ret
= progress
.DoModal();
216 ::DeleteFile(g_Git
.m_CurrentDir
+ _T("\\sys$command"));
218 if( progress
.m_GitStatus
== 0)
220 if(dlg
.m_bAutoloadPuttyKeyFile
)
222 g_Git
.m_CurrentDir
= dlg
.m_Directory
;
223 SetCurrentDirectory(g_Git
.m_CurrentDir
);
225 if(g_Git
.SetConfigValue(_T("remote.origin.puttykeyfile"), dlg
.m_strPuttyKeyFile
, CONFIG_LOCAL
))
227 CMessageBox::Show(NULL
,_T("Fail set config remote.origin.puttykeyfile"),_T("TortoiseGit"),MB_OK
|MB_ICONERROR
);
231 if (ret
== IDC_PROGRESS_BUTTON1
)
233 CString cmd
= _T("/command:log");
234 cmd
+= _T(" /path:\"") + dlg
.m_Directory
+ _T("\"");
235 CAppUtils::RunTortoiseGitProc(cmd
);
238 if (ret
== IDC_PROGRESS_BUTTON1
+ 1)
240 ShellExecute(nullptr, _T("explore"), dlg
.m_Directory
, nullptr, nullptr, SW_SHOW
);