OSDN Git Service

Context Menu Showed
authorFrank Li <lznuaa@gmail.com>
Sat, 8 Nov 2008 01:39:52 +0000 (09:39 +0800)
committerFrank Li <lznuaa@gmail.com>
Sat, 8 Nov 2008 01:39:52 +0000 (09:39 +0800)
TortoiseShell/ContextMenu.cpp
TortoiseShell/GitStatus.h
TortoiseShell/TGitPath.cpp
TortoiseShell/TGitPath.h
TortoiseShell/TortoiseSVN.cpp
TortoiseShell/resource.rc

index e895dfa..6f8267e 100644 (file)
@@ -49,14 +49,14 @@ CShellExt::MenuInfo CShellExt::menuInfo[] =
        { ShellMenuPrevDiff,                                    MENUPREVDIFF,                   IDI_DIFF,                               IDS_MENUPREVDIFF,                       IDS_MENUDESCPREVDIFF,\r
        ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER, 0, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuUrlDiff,                                             MENUURLDIFF,            IDI_DIFF,                               IDS_MENUURLDIFF,                        IDS_MENUDESCURLDIFF,\r
-       ITEMIS_INSVN|ITEMIS_ONLYONE|ITEMIS_EXTENDED, 0, ITEMIS_FOLDERINSVN|ITEMIS_EXTENDED|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuUrlDiff,                                             MENUURLDIFF,            IDI_DIFF,                               IDS_MENUURLDIFF,                        IDS_MENUDESCURLDIFF,\r
+//     ITEMIS_INSVN|ITEMIS_ONLYONE|ITEMIS_EXTENDED, 0, ITEMIS_FOLDERINSVN|ITEMIS_EXTENDED|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
 \r
        { ShellMenuLog,                                                 MENULOG,                        IDI_LOG,                                IDS_MENULOG,                            IDS_MENUDESCLOG,\r
        ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, 0, 0 },\r
 \r
-       { ShellMenuRepoBrowse,                                  MENUREPOBROWSE,         IDI_REPOBROWSE,                 IDS_MENUREPOBROWSE,                     IDS_MENUDESCREPOBROWSE,\r
-       ITEMIS_ONLYONE, 0, ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuRepoBrowse,                                  MENUREPOBROWSE,         IDI_REPOBROWSE,                 IDS_MENUREPOBROWSE,                     IDS_MENUDESCREPOBROWSE,\r
+//     ITEMIS_ONLYONE, 0, ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
 \r
        { ShellMenuShowChanged,                                 MENUSHOWCHANGED,        IDI_SHOWCHANGED,                IDS_MENUSHOWCHANGED,            IDS_MENUDESCSHOWCHANGED,\r
        ITEMIS_INSVN|ITEMIS_ONLYONE, 0, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0},\r
@@ -72,8 +72,8 @@ CShellExt::MenuInfo CShellExt::menuInfo[] =
        { ShellMenuResolve,                                             MENURESOLVE,            IDI_RESOLVE,                    IDS_MENURESOLVE,                        IDS_MENUDESCRESOLVE,\r
        ITEMIS_INSVN|ITEMIS_CONFLICTED, 0, ITEMIS_INSVN|ITEMIS_FOLDER, 0, ITEMIS_FOLDERINSVN, 0, 0, 0 },\r
 \r
-       { ShellMenuUpdateExt,                                   MENUUPDATEEXT,          IDI_UPDATE,                             IDS_MENUUPDATEEXT,                      IDS_MENUDESCUPDATEEXT,\r
-       ITEMIS_INSVN, ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_ADDED, 0, 0, 0, 0 },\r
+//     { ShellMenuUpdateExt,                                   MENUUPDATEEXT,          IDI_UPDATE,                             IDS_MENUUPDATEEXT,                      IDS_MENUDESCUPDATEEXT,\r
+//     ITEMIS_INSVN, ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_ADDED, 0, 0, 0, 0 },\r
 \r
        { ShellMenuRename,                                              MENURENAME,                     IDI_RENAME,                             IDS_MENURENAME,                         IDS_MENUDESCRENAME,\r
        ITEMIS_INSVN|ITEMIS_ONLYONE|ITEMIS_INVERSIONEDFOLDER, 0, 0, 0, 0, 0, 0, 0 },\r
@@ -96,22 +96,22 @@ CShellExt::MenuInfo CShellExt::menuInfo[] =
        { ShellMenuCleanup,                                             MENUCLEANUP,            IDI_CLEANUP,                    IDS_MENUCLEANUP,                        IDS_MENUDESCCLEANUP,\r
        ITEMIS_INSVN|ITEMIS_FOLDER, 0, ITEMIS_FOLDERINSVN|ITEMIS_FOLDER, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuLock,                                                MENULOCK,                       IDI_LOCK,                               IDS_MENU_LOCK,                          IDS_MENUDESC_LOCK,\r
-       ITEMIS_INSVN, ITEMIS_LOCKED|ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_LOCKED|ITEMIS_ADDED, 0, 0, 0, 0 },\r
+//     { ShellMenuLock,                                                MENULOCK,                       IDI_LOCK,                               IDS_MENU_LOCK,                          IDS_MENUDESC_LOCK,\r
+//     ITEMIS_INSVN, ITEMIS_LOCKED|ITEMIS_ADDED, ITEMIS_FOLDERINSVN, ITEMIS_LOCKED|ITEMIS_ADDED, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuUnlock,                                              MENUUNLOCK,                     IDI_UNLOCK,                             IDS_MENU_UNLOCK,                        IDS_MENUDESC_UNLOCK,\r
-       ITEMIS_INSVN|ITEMIS_LOCKED, 0, ITEMIS_FOLDER|ITEMIS_INSVN, 0, ITEMIS_FOLDERINSVN, 0, 0, 0 },\r
+//     { ShellMenuUnlock,                                              MENUUNLOCK,                     IDI_UNLOCK,                             IDS_MENU_UNLOCK,                        IDS_MENUDESC_UNLOCK,\r
+//     ITEMIS_INSVN|ITEMIS_LOCKED, 0, ITEMIS_FOLDER|ITEMIS_INSVN, 0, ITEMIS_FOLDERINSVN, 0, 0, 0 },\r
 \r
-       { ShellMenuUnlockForce,                                 MENUUNLOCK,                     IDI_UNLOCK,                             IDS_MENU_UNLOCKFORCE,           IDS_MENUDESC_UNLOCKFORCE,\r
-       ITEMIS_INSVN|ITEMIS_LOCKED, 0, ITEMIS_FOLDER|ITEMIS_INSVN|ITEMIS_EXTENDED, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuUnlockForce,                                 MENUUNLOCK,                     IDI_UNLOCK,                             IDS_MENU_UNLOCKFORCE,           IDS_MENUDESC_UNLOCKFORCE,\r
+//     ITEMIS_INSVN|ITEMIS_LOCKED, 0, ITEMIS_FOLDER|ITEMIS_INSVN|ITEMIS_EXTENDED, 0, 0, 0, 0, 0 },\r
 \r
        { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
 \r
-       { ShellMenuCopy,                                                MENUCOPY,                       IDI_COPY,                               IDS_MENUBRANCH,                         IDS_MENUDESCCOPY,\r
-       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuCopy,                                                MENUCOPY,                       IDI_COPY,                               IDS_MENUBRANCH,                         IDS_MENUDESCCOPY,\r
+//     ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuSwitch,                                              MENUSWITCH,                     IDI_SWITCH,                             IDS_MENUSWITCH,                         IDS_MENUDESCSWITCH,\r
-       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuSwitch,                                              MENUSWITCH,                     IDI_SWITCH,                             IDS_MENUSWITCH,                         IDS_MENUDESCSWITCH,\r
+//     ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
 \r
        { ShellMenuMerge,                                               MENUMERGE,                      IDI_MERGE,                              IDS_MENUMERGE,                          IDS_MENUDESCMERGE,\r
        ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_ADDED, ITEMIS_FOLDER|ITEMIS_FOLDERINSVN|ITEMIS_ONLYONE, 0, 0, 0, 0, 0 },\r
@@ -135,17 +135,17 @@ CShellExt::MenuInfo CShellExt::menuInfo[] =
        { ShellMenuAddAsReplacement,                    MENUADD,                        IDI_ADD,                                IDS_MENUADDASREPLACEMENT,       IDS_MENUADDASREPLACEMENT,\r
        ITEMIS_DELETED|ITEMIS_ONLYONE, ITEMIS_FOLDER, 0, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuImport,                                              MENUIMPORT,                     IDI_IMPORT,                             IDS_MENUIMPORT,                         IDS_MENUDESCIMPORT,\r
-       ITEMIS_FOLDER, ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuImport,                                              MENUIMPORT,                     IDI_IMPORT,                             IDS_MENUIMPORT,                         IDS_MENUDESCIMPORT,\r
+//     ITEMIS_FOLDER, ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuBlame,                                               MENUBLAME,                      IDI_BLAME,                              IDS_MENUBLAME,                          IDS_MENUDESCBLAME,\r
-       ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuBlame,                                               MENUBLAME,                      IDI_BLAME,                              IDS_MENUBLAME,                          IDS_MENUDESCBLAME,\r
+//     ITEMIS_INSVN|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuIgnoreSub,                                   MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUIGNORE,                         IDS_MENUDESCIGNORE,\r
-       ITEMIS_INVERSIONEDFOLDER, ITEMIS_IGNORED|ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuIgnoreSub,                                   MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUIGNORE,                         IDS_MENUDESCIGNORE,\r
+//     ITEMIS_INVERSIONEDFOLDER, ITEMIS_IGNORED|ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
 \r
-       { ShellMenuUnIgnoreSub,                                 MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUUNIGNORE,                       IDS_MENUDESCUNIGNORE,\r
-       ITEMIS_IGNORED, 0, 0, 0, 0, 0, 0, 0 },\r
+//     { ShellMenuUnIgnoreSub,                                 MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUUNIGNORE,                       IDS_MENUDESCUNIGNORE,\r
+//     ITEMIS_IGNORED, 0, 0, 0, 0, 0, 0, 0 },\r
 \r
        { ShellSeparator, 0, 0, 0, 0, 0, 0, 0, 0},\r
 \r
@@ -193,7 +193,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                    LPDATAOBJECT pDataObj,\r
                                    HKEY /* hRegKey */)\r
 {\r
-#if 0\r
+\r
        ATLTRACE("Shell :: Initialize\n");\r
        PreserveChdir preserveChdir;\r
        files_.clear();\r
@@ -219,6 +219,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                {\r
                        if (m_State == FileStateDropHandler)\r
                        {\r
+\r
                                FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };\r
                                STGMEDIUM stg = { TYMED_HGLOBAL };\r
                                if ( FAILED( pDataObj->GetData ( &etc, &stg )))\r
@@ -272,27 +273,27 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                        try\r
                                                        {\r
                                                                GitStatus stat;\r
-                                                               //stat.GetStatus(CTGitPath(str.c_str()), false, true, true);\r
+                                                               stat.GetStatus(CTGitPath(str.c_str()), false, true, true);\r
                                                                if (stat.status)\r
                                                                {\r
                                                                        statuspath = str;\r
                                                                        status = GitStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
                                                                        fetchedstatus = status;\r
-                                                                       if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
-                                                                               itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
-                                                                       if ((stat.status->entry)&&(stat.status->entry->kind == git_node_dir))\r
-                                                                       {\r
-                                                                               itemStates |= ITEMIS_FOLDER;\r
-                                                                               if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                                                                       itemStates |= ITEMIS_FOLDERINGit;\r
-                                                                       }\r
-                                                                       if ((stat.status->entry)&&(stat.status->entry->present_props))\r
-                                                                       {\r
-                                                                               if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
-                                                                                       itemStates |= ITEMIS_NEEDSLOCK;\r
-                                                                       }\r
-                                                                       if ((stat.status->entry)&&(stat.status->entry->uuid))\r
-                                                                               uuidSource = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+                                                                       //if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+                                                                       //      itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+                                                                       //if ((stat.status->entry)&&(stat.status->entry->kind == git_node_dir))\r
+                                                                       //{\r
+                                                                       //      itemStates |= ITEMIS_FOLDER;\r
+                                                                       //      if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
+                                                                       //              itemStates |= ITEMIS_FOLDERINGit;\r
+                                                                       //}\r
+                                                                       //if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+                                                                       //{\r
+                                                                       //      if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+                                                                       //              itemStates |= ITEMIS_NEEDSLOCK;\r
+                                                                       //}\r
+                                                                       //if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+                                                                       //      uuidSource = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
                                                                }\r
                                                                else\r
                                                                {\r
@@ -308,7 +309,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                                ATLTRACE2(_T("Exception in GitStatus::GetAllStatus()\n"));\r
                                                        }\r
                                                        if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                                               itemStates |= ITEMIS_INGit;\r
+                                                               itemStates |= ITEMIS_INSVN;\r
                                                        if (status == git_wc_status_ignored)\r
                                                                itemStates |= ITEMIS_IGNORED;\r
                                                        if (status == git_wc_status_normal)\r
@@ -324,9 +325,11 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                } // for (int i = 0; i < count; i++)\r
                                GlobalUnlock ( drop );\r
                                ReleaseStgMedium ( &stg );\r
+\r
                        } // if (m_State == FileStateDropHandler) \r
                        else\r
                        {\r
+\r
                                //Enumerate PIDLs which the user has selected\r
                                CIDA* cida = (CIDA*)GlobalLock(medium.hGlobal);\r
                                ItemIDList parent( GetPIDLFolder (cida));\r
@@ -369,23 +372,23 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                                        {\r
                                                                                status = GitStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
                                                                                fetchedstatus = status;\r
-                                                                               if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
-                                                                                       itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
-                                                                               if ((stat.status->entry)&&(stat.status->entry->kind == git_node_dir))\r
-                                                                               {\r
-                                                                                       itemStates |= ITEMIS_FOLDER;\r
-                                                                                       if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                                                                               itemStates |= ITEMIS_FOLDERINGit;\r
-                                                                               }\r
-                                                                               if ((stat.status->entry)&&(stat.status->entry->conflict_wrk))\r
-                                                                                       itemStates |= ITEMIS_CONFLICTED;\r
-                                                                               if ((stat.status->entry)&&(stat.status->entry->present_props))\r
-                                                                               {\r
-                                                                                       if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
-                                                                                               itemStates |= ITEMIS_NEEDSLOCK;\r
-                                                                               }\r
-                                                                               if ((stat.status->entry)&&(stat.status->entry->uuid))\r
-                                                                                       uuidSource = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+                                                                               //if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+                                                                               //      itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+                                                                               //if ((stat.status->entry)&&(stat.status->entry->kind == git_node_dir))\r
+                                                                               //{\r
+                                                                               //      itemStates |= ITEMIS_FOLDER;\r
+                                                                               //      if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
+                                                                               //              itemStates |= ITEMIS_FOLDERINGit;\r
+                                                                               //}\r
+                                                                               //if ((stat.status->entry)&&(stat.status->entry->conflict_wrk))\r
+                                                                               //      itemStates |= ITEMIS_CONFLICTED;\r
+                                                                               //if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+                                                                               //{\r
+                                                                               //      if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+                                                                               //              itemStates |= ITEMIS_NEEDSLOCK;\r
+                                                                               //}\r
+                                                                               //if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+                                                                               //      uuidSource = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
                                                                        }       \r
                                                                        else\r
                                                                        {\r
@@ -406,25 +409,25 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                                }\r
                                                        }\r
                                                        if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                                               itemStates |= ITEMIS_INGit;\r
+                                                               itemStates |= ITEMIS_INSVN;\r
                                                        if (status == git_wc_status_ignored)\r
                                                        {\r
                                                                itemStates |= ITEMIS_IGNORED;\r
                                                                // the item is ignored. Get the svn:ignored properties so we can (maybe) later\r
                                                                // offer a 'remove from ignored list' entry\r
-                                                               GitProperties props(strpath.GetContainingDirectory(), false);\r
-                                                               ignoredprops.empty();\r
-                                                               for (int p=0; p<props.GetCount(); ++p)\r
-                                                               {\r
-                                                                       if (props.GetItemName(p).compare(stdstring(_T("svn:ignore")))==0)\r
-                                                                       {\r
-                                                                               std::string st = props.GetItemValue(p);\r
-                                                                               ignoredprops = MultibyteToWide(st.c_str());\r
-                                                                               // remove all escape chars ('\\')\r
-                                                                               std::remove(ignoredprops.begin(), ignoredprops.end(), '\\');\r
-                                                                               break;\r
-                                                                       }\r
-                                                               }\r
+//                                                             GitProperties props(strpath.GetContainingDirectory(), false);\r
+//                                                             ignoredprops.empty();\r
+//                                                             for (int p=0; p<props.GetCount(); ++p)\r
+//                                                             {\r
+//                                                                     if (props.GetItemName(p).compare(stdstring(_T("svn:ignore")))==0)\r
+//                                                                     {\r
+//                                                                             std::string st = props.GetItemValue(p);\r
+//                                                                             ignoredprops = MultibyteToWide(st.c_str());\r
+//                                                                             // remove all escape chars ('\\')\r
+//                                                                             std::remove(ignoredprops.begin(), ignoredprops.end(), '\\');\r
+//                                                                             break;\r
+//                                                                     }\r
+//                                                             }\r
                                                        }\r
                                                        if (status == git_wc_status_normal)\r
                                                                itemStates |= ITEMIS_NORMAL;\r
@@ -438,8 +441,8 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                        }\r
                                } // for (int i = 0; i < count; ++i)\r
                                ItemIDList child (GetPIDLItem (cida, 0), &parent);\r
-                               if (g_ShellCache.HasGitAdminDir(child.toString().c_str(), FALSE))\r
-                                       itemStates |= ITEMIS_INVERSIONEDFOLDER;\r
+//                             if (g_ShellCache.HasGitAdminDir(child.toString().c_str(), FALSE))\r
+//                                     itemStates |= ITEMIS_INVERSIONEDFOLDER;\r
                                GlobalUnlock(medium.hGlobal);\r
 \r
                                // if the item is a versioned folder, check if there's a patch file\r
@@ -452,6 +455,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                }\r
                                if (IsClipboardFormatAvailable(CF_HDROP)) \r
                                        itemStates |= ITEMIS_PATHINCLIPBOARD;\r
+\r
                        }\r
 \r
                        ReleaseStgMedium ( &medium );\r
@@ -466,6 +470,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
        // get folder background\r
        if (pIDFolder)\r
        {\r
+\r
                ItemIDList list(pIDFolder);\r
                folder_ = list.toString();\r
                git_wc_status_kind status = git_wc_status_none;\r
@@ -482,17 +487,17 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                if (stat.status)\r
                                {\r
                                        status = GitStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
-                                       if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
-                                               itemStatesFolder |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
-                                       if ((stat.status->entry)&&(stat.status->entry->present_props))\r
-                                       {\r
-                                               if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
-                                                       itemStatesFolder |= ITEMIS_NEEDSLOCK;\r
-                                       }\r
-                                       if ((stat.status->entry)&&(stat.status->entry->uuid))\r
-                                               uuidTarget = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+//                                     if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+//                                             itemStatesFolder |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+//                                     if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+//                                     {\r
+//                                             if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+//                                                     itemStatesFolder |= ITEMIS_NEEDSLOCK;\r
+//                                     }\r
+//                                     if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+//                                             uuidTarget = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
                                        if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                               itemStatesFolder |= ITEMIS_INGit;\r
+                                               itemStatesFolder |= ITEMIS_INSVN;\r
                                        if (status == git_wc_status_normal)\r
                                                itemStatesFolder |= ITEMIS_NORMAL;\r
                                        if (status == git_wc_status_conflicted)\r
@@ -522,7 +527,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                }\r
                if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
                {\r
-                       itemStatesFolder |= ITEMIS_FOLDERINGit;\r
+                       itemStatesFolder |= ITEMIS_FOLDERINSVN;\r
                }\r
                if (status == git_wc_status_ignored)\r
                        itemStatesFolder |= ITEMIS_IGNORED;\r
@@ -531,11 +536,13 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                        itemStates |= ITEMIS_ONLYONE;\r
                if (m_State != FileStateDropHandler)\r
                        itemStates |= itemStatesFolder;\r
+\r
        }\r
        if (files_.size() == 2)\r
                itemStates |= ITEMIS_TWO;\r
        if ((files_.size() == 1)&&(g_ShellCache.IsContextPathAllowed(files_.front().c_str())))\r
        {\r
+\r
                itemStates |= ITEMIS_ONLYONE;\r
                if (m_State != FileStateDropHandler)\r
                {\r
@@ -554,15 +561,15 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                if (stat.status)\r
                                                {\r
                                                        status = GitStatus::GetMoreImportant(stat.status->text_status, stat.status->prop_status);\r
-                                                       if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
-                                                               itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
-                                                       if ((stat.status->entry)&&(stat.status->entry->present_props))\r
-                                                       {\r
-                                                               if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
-                                                                       itemStates |= ITEMIS_NEEDSLOCK;\r
-                                                       }\r
-                                                       if ((stat.status->entry)&&(stat.status->entry->uuid))\r
-                                                               uuidTarget = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
+//                                                     if ((stat.status->entry)&&(stat.status->entry->lock_token))\r
+//                                                             itemStates |= (stat.status->entry->lock_token[0] != 0) ? ITEMIS_LOCKED : 0;\r
+//                                                     if ((stat.status->entry)&&(stat.status->entry->present_props))\r
+//                                                     {\r
+//                                                             if (strstr(stat.status->entry->present_props, "svn:needs-lock"))\r
+//                                                                     itemStates |= ITEMIS_NEEDSLOCK;\r
+//                                                     }\r
+//                                                     if ((stat.status->entry)&&(stat.status->entry->uuid))\r
+//                                                             uuidTarget = CUnicodeUtils::StdGetUnicode(stat.status->entry->uuid);\r
                                                }\r
                                        }\r
                                        catch ( ... )\r
@@ -575,7 +582,7 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                        status = fetchedstatus;\r
                                }\r
                                if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                       itemStates |= ITEMIS_FOLDERINGit;\r
+                                       itemStates |= ITEMIS_FOLDERINSVN;\r
                                if (status == git_wc_status_ignored)\r
                                        itemStates |= ITEMIS_IGNORED;\r
                                itemStates |= ITEMIS_FOLDER;\r
@@ -585,8 +592,9 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                        itemStates |= ITEMIS_DELETED;\r
                        }\r
                }\r
+       \r
        }\r
-#endif         \r
+       \r
        return NOERROR;\r
 }\r
 \r
index 440fc99..7a8cc05 100644 (file)
@@ -47,9 +47,17 @@ typedef enum
 \r
 \r
 typedef CString git_revnum_t;\r
-typedef int git_wc_status2_t;\r
 typedef int git_error_t;\r
 \r
+typedef struct git_wc_status2_t\r
+{ \r
+  /** The status of the entries text. */\r
+  git_wc_status_kind text_status;\r
+\r
+  /** The status of the entries properties. */\r
+  git_wc_status_kind prop_status;\r
+}git_wc_status2;\r
+\r
 #define MAX_STATUS_STRING_LENGTH               256\r
 \r
 /**\r
index 8c51170..55b69c5 100644 (file)
+// TortoiseGit - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseGit\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
 #include "StdAfx.h"\r
 #include "TGitPath.h"\r
+#include "UnicodeUtils.h"\r
+#include "GitAdminDir.h"\r
+#include "PathUtils.h"\r
+#include <regex>\r
+\r
+#if defined(_MFC_VER)\r
+#include "MessageBox.h"\r
+#include "AppUtils.h"\r
+#endif\r
 \r
-CTGitPath::CTGitPath(void)\r
+using namespace std;\r
+\r
+\r
+CTGitPath::CTGitPath(void) :\r
+       m_bDirectoryKnown(false),\r
+       m_bIsDirectory(false),\r
+       m_bIsURL(false),\r
+       m_bURLKnown(false),\r
+       m_bHasAdminDirKnown(false),\r
+       m_bHasAdminDir(false),\r
+       m_bIsValidOnWindowsKnown(false),\r
+       m_bIsReadOnly(false),\r
+       m_bIsAdminDirKnown(false),\r
+       m_bIsAdminDir(false),\r
+       m_bExists(false),\r
+       m_bExistsKnown(false),\r
+       m_bLastWriteTimeKnown(0),\r
+       m_lastWriteTime(0),\r
+       m_customData(NULL),\r
+       m_bIsSpecialDirectoryKnown(false),\r
+       m_bIsSpecialDirectory(false)\r
 {\r
 }\r
 \r
 CTGitPath::~CTGitPath(void)\r
 {\r
 }\r
+// Create a TGitPath object from an unknown path type (same as using SetFromUnknown)\r
+CTGitPath::CTGitPath(const CString& sUnknownPath) :\r
+       m_bDirectoryKnown(false),\r
+       m_bIsDirectory(false),\r
+       m_bIsURL(false),\r
+       m_bURLKnown(false),\r
+       m_bHasAdminDirKnown(false),\r
+       m_bHasAdminDir(false),\r
+       m_bIsValidOnWindowsKnown(false),\r
+       m_bIsReadOnly(false),\r
+       m_bIsAdminDirKnown(false),\r
+       m_bIsAdminDir(false),\r
+       m_bExists(false),\r
+       m_bExistsKnown(false),\r
+       m_bLastWriteTimeKnown(0),\r
+       m_lastWriteTime(0),\r
+       m_customData(NULL),\r
+       m_bIsSpecialDirectoryKnown(false),\r
+       m_bIsSpecialDirectory(false)\r
+{\r
+       SetFromUnknown(sUnknownPath);\r
+}\r
+\r
+void CTGitPath::SetFromGit(const char* pPath)\r
+{\r
+       Reset();\r
+       if (pPath == NULL)\r
+               return;\r
+       int len = MultiByteToWideChar(CP_UTF8, 0, pPath, -1, NULL, 0);\r
+       if (len)\r
+       {\r
+               len = MultiByteToWideChar(CP_UTF8, 0, pPath, -1, m_sFwdslashPath.GetBuffer(len+1), len+1);\r
+               m_sFwdslashPath.ReleaseBuffer(len-1);\r
+       }\r
+       SanitizeRootPath(m_sFwdslashPath, true);\r
+}\r
+\r
+void CTGitPath::SetFromGit(const char* pPath, bool bIsDirectory)\r
+{\r
+       SetFromGit(pPath);\r
+       m_bDirectoryKnown = true;\r
+       m_bIsDirectory = bIsDirectory;\r
+}\r
+\r
+void CTGitPath::SetFromGit(const CString& sPath)\r
+{\r
+       Reset();\r
+       m_sFwdslashPath = sPath;\r
+       SanitizeRootPath(m_sFwdslashPath, true);\r
+}\r
+\r
+void CTGitPath::SetFromWin(LPCTSTR pPath)\r
+{\r
+       Reset();\r
+       m_sBackslashPath = pPath;\r
+       SanitizeRootPath(m_sBackslashPath, false);\r
+       ATLASSERT(m_sBackslashPath.Find('/')<0);\r
+}\r
+void CTGitPath::SetFromWin(const CString& sPath)\r
+{\r
+       Reset();\r
+       m_sBackslashPath = sPath;\r
+       SanitizeRootPath(m_sBackslashPath, false);\r
+}\r
+void CTGitPath::SetFromWin(const CString& sPath, bool bIsDirectory)\r
+{\r
+       Reset();\r
+       m_sBackslashPath = sPath;\r
+       m_bIsDirectory = bIsDirectory;\r
+       m_bDirectoryKnown = true;\r
+       SanitizeRootPath(m_sBackslashPath, false);\r
+}\r
+void CTGitPath::SetFromUnknown(const CString& sPath)\r
+{\r
+       Reset();\r
+       // Just set whichever path we think is most likely to be used\r
+       SetFwdslashPath(sPath);\r
+}\r
+\r
+LPCTSTR CTGitPath::GetWinPath() const\r
+{\r
+       if(IsEmpty())\r
+       {\r
+               return _T("");\r
+       }\r
+       if(m_sBackslashPath.IsEmpty())\r
+       {\r
+               SetBackslashPath(m_sFwdslashPath);\r
+       }\r
+       return m_sBackslashPath;\r
+}\r
+// This is a temporary function, to be used during the migration to \r
+// the path class.  Ultimately, functions consuming paths should take a CTGitPath&, not a CString\r
+const CString& CTGitPath::GetWinPathString() const\r
+{\r
+       if(m_sBackslashPath.IsEmpty())\r
+       {\r
+               SetBackslashPath(m_sFwdslashPath);\r
+       }\r
+       return m_sBackslashPath;\r
+}\r
+\r
+const CString& CTGitPath::GetGitPathString() const\r
+{\r
+       if(m_sFwdslashPath.IsEmpty())\r
+       {\r
+               SetFwdslashPath(m_sBackslashPath);\r
+       }\r
+       return m_sFwdslashPath;\r
+}\r
+\r
+#if 0\r
+const char* CTGitPath::GetGitApiPath(apr_pool_t *pool) const\r
+{\r
+       // This funny-looking 'if' is to avoid a subtle problem with empty paths, whereby\r
+       // each call to GetGitApiPath returns a different pointer value.\r
+       // If you made multiple calls to GetGitApiPath on the same string, only the last\r
+       // one would give you a valid pointer to an empty string, because each \r
+       // call would invalidate the previous call's return. \r
+       if(IsEmpty())\r
+       {\r
+               return "";\r
+       }\r
+       if(m_sFwdslashPath.IsEmpty())\r
+       {\r
+               SetFwdslashPath(m_sBackslashPath);\r
+       }\r
+       if(m_sUTF8FwdslashPath.IsEmpty())\r
+       {\r
+               SetUTF8FwdslashPath(m_sFwdslashPath);\r
+       }\r
+       if (svn_path_is_url(m_sUTF8FwdslashPath))\r
+       {\r
+               m_sUTF8FwdslashPathEscaped = CPathUtils::PathEscape(m_sUTF8FwdslashPath);\r
+               m_sUTF8FwdslashPathEscaped.Replace("file:////", "file:///\\");\r
+               m_sUTF8FwdslashPathEscaped = svn_path_canonicalize(m_sUTF8FwdslashPathEscaped, pool);\r
+               return m_sUTF8FwdslashPathEscaped;\r
+       }\r
+       m_sUTF8FwdslashPath = svn_path_canonicalize(m_sUTF8FwdslashPath, pool);\r
+\r
+       return m_sUTF8FwdslashPath;\r
+}\r
+#endif\r
+\r
+const CString& CTGitPath::GetUIPathString() const\r
+{\r
+       if (m_sUIPath.IsEmpty())\r
+       {\r
+#if defined(_MFC_VER)\r
+               //BUGBUG HORRIBLE!!! - CPathUtils::IsEscaped doesn't need to be MFC-only\r
+               if (IsUrl())\r
+               {\r
+                       m_sUIPath = CPathUtils::PathUnescape(GetGitPathString());\r
+                       m_sUIPath.Replace(_T("file:////"), _T("file:///\\"));\r
+\r
+               }\r
+               else\r
+#endif \r
+               {\r
+                       m_sUIPath = GetWinPathString();\r
+               }\r
+       }\r
+       return m_sUIPath;\r
+}\r
+\r
+void CTGitPath::SetFwdslashPath(const CString& sPath) const\r
+{\r
+       m_sFwdslashPath = sPath;\r
+       m_sFwdslashPath.Replace('\\', '/');\r
+\r
+       // We don't leave a trailing /\r
+       m_sFwdslashPath.TrimRight('/'); \r
+\r
+       SanitizeRootPath(m_sFwdslashPath, true);\r
+\r
+       m_sFwdslashPath.Replace(_T("file:////"), _T("file:///\\"));\r
+\r
+       m_sUTF8FwdslashPath.Empty();\r
+}\r
+\r
+void CTGitPath::SetBackslashPath(const CString& sPath) const\r
+{\r
+       m_sBackslashPath = sPath;\r
+       m_sBackslashPath.Replace('/', '\\');\r
+       m_sBackslashPath.TrimRight('\\');\r
+       SanitizeRootPath(m_sBackslashPath, false);\r
+}\r
+\r
+void CTGitPath::SetUTF8FwdslashPath(const CString& sPath) const\r
+{\r
+       m_sUTF8FwdslashPath = CUnicodeUtils::GetUTF8(sPath);\r
+}\r
+\r
+void CTGitPath::SanitizeRootPath(CString& sPath, bool bIsForwardPath) const\r
+{\r
+       // Make sure to add the trailing slash to root paths such as 'C:'\r
+       if (sPath.GetLength() == 2 && sPath[1] == ':')\r
+       {\r
+               sPath += (bIsForwardPath) ? _T("/") : _T("\\");\r
+       }\r
+}\r
+\r
+bool CTGitPath::IsUrl() const\r
+{\r
+#if 0\r
+       if (!m_bURLKnown)\r
+       {\r
+               EnsureFwdslashPathSet();\r
+               if(m_sUTF8FwdslashPath.IsEmpty())\r
+               {\r
+                       SetUTF8FwdslashPath(m_sFwdslashPath);\r
+               }\r
+               m_bIsURL = !!svn_path_is_url(m_sUTF8FwdslashPath);\r
+               m_bURLKnown = true;\r
+       }\r
+       return m_bIsURL;\r
+#endif \r
+       return false;\r
+}\r
+\r
+bool CTGitPath::IsDirectory() const\r
+{\r
+       if(!m_bDirectoryKnown)\r
+       {\r
+               UpdateAttributes();\r
+       }\r
+       return m_bIsDirectory;\r
+}\r
+\r
+bool CTGitPath::Exists() const\r
+{\r
+       if (!m_bExistsKnown)\r
+       {\r
+               UpdateAttributes();\r
+       }\r
+       return m_bExists;\r
+}\r
+\r
+bool CTGitPath::Delete(bool bTrash) const\r
+{\r
+       EnsureBackslashPathSet();\r
+       ::SetFileAttributes(m_sBackslashPath, FILE_ATTRIBUTE_NORMAL);\r
+       bool bRet = false;\r
+       if (Exists())\r
+       {\r
+               if ((bTrash)||(IsDirectory()))\r
+               {\r
+                       TCHAR * buf = new TCHAR[m_sBackslashPath.GetLength()+2];\r
+                       _tcscpy_s(buf, m_sBackslashPath.GetLength()+2, m_sBackslashPath);\r
+                       buf[m_sBackslashPath.GetLength()] = 0;\r
+                       buf[m_sBackslashPath.GetLength()+1] = 0;\r
+                       SHFILEOPSTRUCT shop = {0};\r
+                       shop.wFunc = FO_DELETE;\r
+                       shop.pFrom = buf;\r
+                       shop.fFlags = FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT;\r
+                       if (bTrash)\r
+                               shop.fFlags |= FOF_ALLOWUNDO;\r
+                       bRet = (SHFileOperation(&shop) == 0);\r
+                       delete [] buf;\r
+               }\r
+               else\r
+               {\r
+                       bRet = !!::DeleteFile(m_sBackslashPath);\r
+               }\r
+       }\r
+       m_bExists = false;\r
+       m_bExistsKnown = true;\r
+       return bRet;\r
+}\r
+\r
+__int64  CTGitPath::GetLastWriteTime() const\r
+{\r
+       if(!m_bLastWriteTimeKnown)\r
+       {\r
+               UpdateAttributes();\r
+       }\r
+       return m_lastWriteTime;\r
+}\r
+\r
+bool CTGitPath::IsReadOnly() const\r
+{\r
+       if(!m_bLastWriteTimeKnown)\r
+       {\r
+               UpdateAttributes();\r
+       }\r
+       return m_bIsReadOnly;\r
+}\r
+\r
+void CTGitPath::UpdateAttributes() const\r
+{\r
+       EnsureBackslashPathSet();\r
+       WIN32_FILE_ATTRIBUTE_DATA attribs;\r
+       if(GetFileAttributesEx(m_sBackslashPath, GetFileExInfoStandard, &attribs))\r
+       {\r
+               m_bIsDirectory = !!(attribs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);\r
+               m_lastWriteTime = *(__int64*)&attribs.ftLastWriteTime;\r
+               m_bIsReadOnly = !!(attribs.dwFileAttributes & FILE_ATTRIBUTE_READONLY);\r
+               m_bExists = true;\r
+       }\r
+       else\r
+       {\r
+               DWORD err = GetLastError();\r
+               if ((err == ERROR_FILE_NOT_FOUND)||(err == ERROR_PATH_NOT_FOUND)||(err == ERROR_INVALID_NAME))\r
+               {\r
+                       m_bIsDirectory = false;\r
+                       m_lastWriteTime = 0;\r
+                       m_bExists = false;\r
+               }\r
+               else\r
+               {\r
+                       m_bIsDirectory = false;\r
+                       m_lastWriteTime = 0;\r
+                       m_bExists = true;\r
+                       return;\r
+               }\r
+       }\r
+       m_bDirectoryKnown = true;\r
+       m_bLastWriteTimeKnown = true;\r
+       m_bExistsKnown = true;\r
+}\r
+\r
+\r
+void CTGitPath::EnsureBackslashPathSet() const\r
+{\r
+       if(m_sBackslashPath.IsEmpty())\r
+       {\r
+               SetBackslashPath(m_sFwdslashPath);\r
+               ATLASSERT(IsEmpty() || !m_sBackslashPath.IsEmpty());\r
+       }\r
+}\r
+void CTGitPath::EnsureFwdslashPathSet() const\r
+{\r
+       if(m_sFwdslashPath.IsEmpty())\r
+       {\r
+               SetFwdslashPath(m_sBackslashPath);\r
+               ATLASSERT(IsEmpty() || !m_sFwdslashPath.IsEmpty());\r
+       }\r
+}\r
+\r
+\r
+// Reset all the caches\r
+void CTGitPath::Reset()\r
+{\r
+       m_bDirectoryKnown = false;\r
+       m_bURLKnown = false;\r
+       m_bLastWriteTimeKnown = false;\r
+       m_bHasAdminDirKnown = false;\r
+       m_bIsValidOnWindowsKnown = false;\r
+       m_bIsAdminDirKnown = false;\r
+       m_bExistsKnown = false;\r
+       m_bIsSpecialDirectoryKnown = false;\r
+       m_bIsSpecialDirectory = false;\r
+\r
+       m_sBackslashPath.Empty();\r
+       m_sFwdslashPath.Empty();\r
+       m_sUTF8FwdslashPath.Empty();\r
+       ATLASSERT(IsEmpty());\r
+}\r
+\r
+CTGitPath CTGitPath::GetDirectory() const\r
+{\r
+       if ((IsDirectory())||(!Exists()))\r
+       {\r
+               return *this;\r
+       }\r
+       return GetContainingDirectory();\r
+}\r
+\r
+CTGitPath CTGitPath::GetContainingDirectory() const\r
+{\r
+       EnsureBackslashPathSet();\r
+\r
+       CString sDirName = m_sBackslashPath.Left(m_sBackslashPath.ReverseFind('\\'));\r
+       if(sDirName.GetLength() == 2 && sDirName[1] == ':')\r
+       {\r
+               // This is a root directory, which needs a trailing slash\r
+               sDirName += '\\';\r
+               if(sDirName == m_sBackslashPath)\r
+               {\r
+                       // We were clearly provided with a root path to start with - we should return nothing now\r
+                       sDirName.Empty();\r
+               }\r
+       }\r
+       if(sDirName.GetLength() == 1 && sDirName[0] == '\\')\r
+       {\r
+               // We have an UNC path and we already are the root\r
+               sDirName.Empty();\r
+       }\r
+       CTGitPath retVal;\r
+       retVal.SetFromWin(sDirName);\r
+       return retVal;\r
+}\r
+\r
+CString CTGitPath::GetRootPathString() const\r
+{\r
+       EnsureBackslashPathSet();\r
+       CString workingPath = m_sBackslashPath;\r
+       LPTSTR pPath = workingPath.GetBuffer(MAX_PATH);         // MAX_PATH ok here.\r
+       ATLVERIFY(::PathStripToRoot(pPath));\r
+       workingPath.ReleaseBuffer();\r
+       return workingPath;\r
+}\r
+\r
+\r
+CString CTGitPath::GetFilename() const\r
+{\r
+       ATLASSERT(!IsDirectory());\r
+       return GetFileOrDirectoryName();\r
+}\r
+\r
+CString CTGitPath::GetFileOrDirectoryName() const\r
+{\r
+       EnsureBackslashPathSet();\r
+       return m_sBackslashPath.Mid(m_sBackslashPath.ReverseFind('\\')+1);\r
+}\r
+\r
+CString CTGitPath::GetUIFileOrDirectoryName() const\r
+{\r
+       GetUIPathString();\r
+       return m_sUIPath.Mid(m_sUIPath.ReverseFind('\\')+1);\r
+}\r
+\r
+CString CTGitPath::GetFileExtension() const\r
+{\r
+       if(!IsDirectory())\r
+       {\r
+               EnsureBackslashPathSet();\r
+               int dotPos = m_sBackslashPath.ReverseFind('.');\r
+               int slashPos = m_sBackslashPath.ReverseFind('\\');\r
+               if (dotPos > slashPos)\r
+                       return m_sBackslashPath.Mid(dotPos);\r
+       }\r
+       return CString();\r
+}\r
+\r
+\r
+bool CTGitPath::ArePathStringsEqual(const CString& sP1, const CString& sP2)\r
+{\r
+       int length = sP1.GetLength();\r
+       if(length != sP2.GetLength())\r
+       {\r
+               // Different lengths\r
+               return false;\r
+       }\r
+       // We work from the end of the strings, because path differences\r
+       // are more likely to occur at the far end of a string\r
+       LPCTSTR pP1Start = sP1;\r
+       LPCTSTR pP1 = pP1Start+(length-1);\r
+       LPCTSTR pP2 = ((LPCTSTR)sP2)+(length-1);\r
+       while(length-- > 0)\r
+       {\r
+               if(_totlower(*pP1--) != _totlower(*pP2--))\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+       return true;\r
+}\r
+\r
+bool CTGitPath::ArePathStringsEqualWithCase(const CString& sP1, const CString& sP2)\r
+{\r
+       int length = sP1.GetLength();\r
+       if(length != sP2.GetLength())\r
+       {\r
+               // Different lengths\r
+               return false;\r
+       }\r
+       // We work from the end of the strings, because path differences\r
+       // are more likely to occur at the far end of a string\r
+       LPCTSTR pP1Start = sP1;\r
+       LPCTSTR pP1 = pP1Start+(length-1);\r
+       LPCTSTR pP2 = ((LPCTSTR)sP2)+(length-1);\r
+       while(length-- > 0)\r
+       {\r
+               if((*pP1--) != (*pP2--))\r
+               {\r
+                       return false;\r
+               }\r
+       }\r
+       return true;\r
+}\r
+\r
+bool CTGitPath::IsEmpty() const\r
+{\r
+       // Check the backward slash path first, since the chance that this\r
+       // one is set is higher. In case of a 'false' return value it's a little\r
+       // bit faster.\r
+       return m_sBackslashPath.IsEmpty() && m_sFwdslashPath.IsEmpty();\r
+}\r
+\r
+// Test if both paths refer to the same item\r
+// Ignores case and slash direction\r
+bool CTGitPath::IsEquivalentTo(const CTGitPath& rhs) const\r
+{\r
+       // Try and find a slash direction which avoids having to convert\r
+       // both filenames\r
+       if(!m_sBackslashPath.IsEmpty())\r
+       {\r
+               // *We've* got a \ path - make sure that the RHS also has a \ path\r
+               rhs.EnsureBackslashPathSet();\r
+               return ArePathStringsEqualWithCase(m_sBackslashPath, rhs.m_sBackslashPath);\r
+       }\r
+       else\r
+       {\r
+               // Assume we've got a fwdslash path and make sure that the RHS has one\r
+               rhs.EnsureFwdslashPathSet();\r
+               return ArePathStringsEqualWithCase(m_sFwdslashPath, rhs.m_sFwdslashPath);\r
+       }\r
+}\r
+\r
+bool CTGitPath::IsEquivalentToWithoutCase(const CTGitPath& rhs) const\r
+{\r
+       // Try and find a slash direction which avoids having to convert\r
+       // both filenames\r
+       if(!m_sBackslashPath.IsEmpty())\r
+       {\r
+               // *We've* got a \ path - make sure that the RHS also has a \ path\r
+               rhs.EnsureBackslashPathSet();\r
+               return ArePathStringsEqual(m_sBackslashPath, rhs.m_sBackslashPath);\r
+       }\r
+       else\r
+       {\r
+               // Assume we've got a fwdslash path and make sure that the RHS has one\r
+               rhs.EnsureFwdslashPathSet();\r
+               return ArePathStringsEqual(m_sFwdslashPath, rhs.m_sFwdslashPath);\r
+       }\r
+}\r
+\r
+bool CTGitPath::IsAncestorOf(const CTGitPath& possibleDescendant) const\r
+{\r
+       possibleDescendant.EnsureBackslashPathSet();\r
+       EnsureBackslashPathSet();\r
+\r
+       bool bPathStringsEqual = ArePathStringsEqual(m_sBackslashPath, possibleDescendant.m_sBackslashPath.Left(m_sBackslashPath.GetLength()));\r
+       if (m_sBackslashPath.GetLength() >= possibleDescendant.GetWinPathString().GetLength())\r
+       {\r
+               return bPathStringsEqual;               \r
+       }\r
+       \r
+       return (bPathStringsEqual && \r
+                       ((possibleDescendant.m_sBackslashPath[m_sBackslashPath.GetLength()] == '\\')||\r
+                       (m_sBackslashPath.GetLength()==3 && m_sBackslashPath[1]==':')));\r
+}\r
+\r
+// Get a string representing the file path, optionally with a base \r
+// section stripped off the front.\r
+CString CTGitPath::GetDisplayString(const CTGitPath* pOptionalBasePath /* = NULL*/) const\r
+{\r
+       EnsureFwdslashPathSet();\r
+       if(pOptionalBasePath != NULL)\r
+       {\r
+               // Find the length of the base-path without having to do an 'ensure' on it\r
+               int baseLength = max(pOptionalBasePath->m_sBackslashPath.GetLength(), pOptionalBasePath->m_sFwdslashPath.GetLength());\r
+\r
+               // Now, chop that baseLength of the front of the path\r
+               return m_sFwdslashPath.Mid(baseLength).TrimLeft('/');\r
+       }\r
+       return m_sFwdslashPath;\r
+}\r
+\r
+int CTGitPath::Compare(const CTGitPath& left, const CTGitPath& right)\r
+{\r
+       left.EnsureBackslashPathSet();\r
+       right.EnsureBackslashPathSet();\r
+       return left.m_sBackslashPath.CompareNoCase(right.m_sBackslashPath);\r
+}\r
+\r
+bool operator<(const CTGitPath& left, const CTGitPath& right)\r
+{\r
+       return CTGitPath::Compare(left, right) < 0;\r
+}\r
+\r
+bool CTGitPath::PredLeftEquivalentToRight(const CTGitPath& left, const CTGitPath& right)\r
+{\r
+       return left.IsEquivalentTo(right);\r
+}\r
+\r
+bool CTGitPath::PredLeftSameWCPathAsRight(const CTGitPath& left, const CTGitPath& right)\r
+{\r
+       if (left.IsAdminDir() && right.IsAdminDir())\r
+       {\r
+               CTGitPath l = left;\r
+               CTGitPath r = right;\r
+               do \r
+               {\r
+                       l = l.GetContainingDirectory();\r
+               } while(l.HasAdminDir());\r
+               do \r
+               {\r
+                       r = r.GetContainingDirectory();\r
+               } while(r.HasAdminDir());\r
+               return l.GetContainingDirectory().IsEquivalentTo(r.GetContainingDirectory());\r
+       }\r
+       return left.GetDirectory().IsEquivalentTo(right.GetDirectory());\r
+}\r
+\r
+bool CTGitPath::CheckChild(const CTGitPath &parent, const CTGitPath& child)\r
+{\r
+       return parent.IsAncestorOf(child);\r
+}\r
+\r
+void CTGitPath::AppendRawString(const CString& sAppend)\r
+{\r
+       EnsureFwdslashPathSet();\r
+       CString strCopy = m_sFwdslashPath += sAppend;\r
+       SetFromUnknown(strCopy);\r
+}\r
+\r
+void CTGitPath::AppendPathString(const CString& sAppend)\r
+{\r
+       EnsureBackslashPathSet();\r
+       CString cleanAppend(sAppend);\r
+       cleanAppend.Replace('/', '\\');\r
+       cleanAppend.TrimLeft('\\');\r
+       m_sBackslashPath.TrimRight('\\');\r
+       CString strCopy = m_sBackslashPath + _T("\\") + cleanAppend;\r
+       SetFromWin(strCopy);\r
+}\r
+\r
+bool CTGitPath::HasAdminDir() const\r
+{\r
+       if (m_bHasAdminDirKnown)\r
+               return m_bHasAdminDir;\r
+\r
+       EnsureBackslashPathSet();\r
+       m_bHasAdminDir = g_GitAdminDir.HasAdminDir(m_sBackslashPath, IsDirectory());\r
+       m_bHasAdminDirKnown = true;\r
+       return m_bHasAdminDir;\r
+}\r
+\r
+bool CTGitPath::IsAdminDir() const\r
+{\r
+       if (m_bIsAdminDirKnown)\r
+               return m_bIsAdminDir;\r
+       \r
+       EnsureBackslashPathSet();\r
+       m_bIsAdminDir = g_GitAdminDir.IsAdminDirPath(m_sBackslashPath);\r
+       m_bIsAdminDirKnown = true;\r
+       return m_bIsAdminDir;\r
+}\r
+\r
+bool CTGitPath::IsValidOnWindows() const\r
+{\r
+       if (m_bIsValidOnWindowsKnown)\r
+               return m_bIsValidOnWindows;\r
+\r
+       m_bIsValidOnWindows = false;\r
+       EnsureBackslashPathSet();\r
+       CString sMatch = m_sBackslashPath + _T("\r\n");\r
+       wstring sPattern;\r
+       // the 'file://' URL is just a normal windows path:\r
+       if (sMatch.Left(7).CompareNoCase(_T("file:\\\\"))==0)\r
+       {\r
+               sMatch = sMatch.Mid(7);\r
+               sMatch.TrimLeft(_T("\\"));\r
+               sPattern = _T("^(\\\\\\\\\\?\\\\)?(([a-zA-Z]:|\\\\)\\\\)?(((\\.)|(\\.\\.)|([^\\\\/:\\*\\?\"\\|<> ](([^\\\\/:\\*\\?\"\\|<>\\. ])|([^\\\\/:\\*\\?\"\\|<>]*[^\\\\/:\\*\\?\"\\|<>\\. ]))?))\\\\)*[^\\\\/:\\*\\?\"\\|<> ](([^\\\\/:\\*\\?\"\\|<>\\. ])|([^\\\\/:\\*\\?\"\\|<>]*[^\\\\/:\\*\\?\"\\|<>\\. ]))?$");\r
+       }\r
+       else if (IsUrl())\r
+       {\r
+               sPattern = _T("^((http|https|svn|svn\\+ssh|file)\\:\\\\+([^\\\\@\\:]+\\:[^\\\\@\\:]+@)?\\\\[^\\\\]+(\\:\\d+)?)?(((\\.)|(\\.\\.)|([^\\\\/:\\*\\?\"\\|<>\\. ](([^\\\\/:\\*\\?\"\\|<>\\. ])|([^\\\\/:\\*\\?\"\\|<>]*[^\\\\/:\\*\\?\"\\|<>\\. ]))?))\\\\)*[^\\\\/:\\*\\?\"\\|<>\\. ](([^\\\\/:\\*\\?\"\\|<>\\. ])|([^\\\\/:\\*\\?\"\\|<>]*[^\\\\/:\\*\\?\"\\|<>\\. ]))?$");\r
+       }\r
+       else\r
+       {\r
+               sPattern = _T("^(\\\\\\\\\\?\\\\)?(([a-zA-Z]:|\\\\)\\\\)?(((\\.)|(\\.\\.)|([^\\\\/:\\*\\?\"\\|<> ](([^\\\\/:\\*\\?\"\\|<>\\. ])|([^\\\\/:\\*\\?\"\\|<>]*[^\\\\/:\\*\\?\"\\|<>\\. ]))?))\\\\)*[^\\\\/:\\*\\?\"\\|<> ](([^\\\\/:\\*\\?\"\\|<>\\. ])|([^\\\\/:\\*\\?\"\\|<>]*[^\\\\/:\\*\\?\"\\|<>\\. ]))?$");\r
+       }\r
+\r
+       try\r
+       {\r
+               tr1::wregex rx(sPattern, tr1::regex_constants::icase | tr1::regex_constants::ECMAScript);\r
+               tr1::wsmatch match;\r
+\r
+               wstring rmatch = wstring((LPCTSTR)sMatch);\r
+               if (tr1::regex_match(rmatch, match, rx))\r
+               {\r
+                       if (wstring(match[0]).compare(sMatch)==0)\r
+                               m_bIsValidOnWindows = true;\r
+               }\r
+               if (m_bIsValidOnWindows)\r
+               {\r
+                       // now check for illegal filenames\r
+                       tr1::wregex rx2(_T("\\\\(lpt\\d|com\\d|aux|nul|prn|con)(\\\\|$)"), tr1::regex_constants::icase | tr1::regex_constants::ECMAScript);\r
+                       rmatch = m_sBackslashPath;\r
+                       if (tr1::regex_search(rmatch, rx2, tr1::regex_constants::match_default))\r
+                               m_bIsValidOnWindows = false;\r
+               }\r
+       }\r
+       catch (exception) {}\r
+\r
+       m_bIsValidOnWindowsKnown = true;\r
+       return m_bIsValidOnWindows;\r
+}\r
+\r
+bool CTGitPath::IsSpecialDirectory() const\r
+{\r
+       if (m_bIsSpecialDirectoryKnown)\r
+               return m_bIsSpecialDirectory;\r
+\r
+       static LPCTSTR specialDirectories[]\r
+               = { _T("trunk"), _T("tags"), _T("branches") };\r
+\r
+       for (int i=0 ; i<(sizeof(specialDirectories) / sizeof(specialDirectories[0])) ; ++i)\r
+       {\r
+               CString name = GetFileOrDirectoryName();\r
+               if (0 == name.CompareNoCase(specialDirectories[i]))\r
+               {\r
+                       m_bIsSpecialDirectory = true;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       m_bIsSpecialDirectoryKnown = true;\r
+\r
+       return m_bIsSpecialDirectory;\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
+CTGitPathList::CTGitPathList()\r
+{\r
+\r
+}\r
+\r
+// A constructor which allows a path list to be easily built which one initial entry in\r
+CTGitPathList::CTGitPathList(const CTGitPath& firstEntry)\r
+{\r
+       AddPath(firstEntry);\r
+}\r
+\r
+void CTGitPathList::AddPath(const CTGitPath& newPath)\r
+{\r
+       m_paths.push_back(newPath);\r
+       m_commonBaseDirectory.Reset();\r
+}\r
+int CTGitPathList::GetCount() const\r
+{\r
+       return (int)m_paths.size();\r
+}\r
+void CTGitPathList::Clear()\r
+{\r
+       m_paths.clear();\r
+       m_commonBaseDirectory.Reset();\r
+}\r
+\r
+const CTGitPath& CTGitPathList::operator[](INT_PTR index) const\r
+{\r
+       ATLASSERT(index >= 0 && index < (INT_PTR)m_paths.size());\r
+       return m_paths[index];\r
+}\r
+\r
+bool CTGitPathList::AreAllPathsFiles() const\r
+{\r
+       // Look through the vector for any directories - if we find them, return false\r
+       return std::find_if(m_paths.begin(), m_paths.end(), std::mem_fun_ref(&CTGitPath::IsDirectory)) == m_paths.end();\r
+}\r
+\r
+\r
+#if defined(_MFC_VER)\r
+\r
+bool CTGitPathList::LoadFromFile(const CTGitPath& filename)\r
+{\r
+       Clear();\r
+       try\r
+       {\r
+               CString strLine;\r
+               CStdioFile file(filename.GetWinPath(), CFile::typeBinary | CFile::modeRead | CFile::shareDenyWrite);\r
+\r
+               // for every selected file/folder\r
+               CTGitPath path;\r
+               while (file.ReadString(strLine))\r
+               {\r
+                       path.SetFromUnknown(strLine);\r
+                       AddPath(path);\r
+               }\r
+               file.Close();\r
+       }\r
+       catch (CFileException* pE)\r
+       {\r
+               TRACE("CFileException loading target file list\n");\r
+               TCHAR error[10000] = {0};\r
+               pE->GetErrorMessage(error, 10000);\r
+               CMessageBox::Show(NULL, error, _T("TortoiseGit"), MB_ICONERROR);\r
+               pE->Delete();\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+bool CTGitPathList::WriteToFile(const CString& sFilename, bool bANSI /* = false */) const\r
+{\r
+       try\r
+       {\r
+               if (bANSI)\r
+               {\r
+                       CStdioFile file(sFilename, CFile::typeText | CFile::modeReadWrite | CFile::modeCreate);\r
+                       PathVector::const_iterator it;\r
+                       for(it = m_paths.begin(); it != m_paths.end(); ++it)\r
+                       {\r
+                               CStringA line = CStringA(it->GetGitPathString()) + '\n';\r
+                               file.Write(line, line.GetLength());\r
+                       } \r
+                       file.Close();\r
+               }\r
+               else\r
+               {\r
+                       CStdioFile file(sFilename, CFile::typeBinary | CFile::modeReadWrite | CFile::modeCreate);\r
+                       PathVector::const_iterator it;\r
+                       for(it = m_paths.begin(); it != m_paths.end(); ++it)\r
+                       {\r
+                               file.WriteString(it->GetGitPathString()+_T("\n"));\r
+                       } \r
+                       file.Close();\r
+               }\r
+       }\r
+       catch (CFileException* pE)\r
+       {\r
+               TRACE("CFileException in writing temp file\n");\r
+               pE->Delete();\r
+               return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+\r
+void CTGitPathList::LoadFromAsteriskSeparatedString(const CString& sPathString)\r
+{\r
+       int pos = 0;\r
+       CString temp;\r
+       for(;;)\r
+       {\r
+               temp = sPathString.Tokenize(_T("*"),pos);\r
+               if(temp.IsEmpty())\r
+               {\r
+                       break;\r
+               }\r
+               AddPath(CTGitPath(CPathUtils::GetLongPathname(temp)));\r
+       } \r
+}\r
+\r
+CString CTGitPathList::CreateAsteriskSeparatedString() const\r
+{\r
+       CString sRet;\r
+       PathVector::const_iterator it;\r
+       for(it = m_paths.begin(); it != m_paths.end(); ++it)\r
+       {\r
+               if (!sRet.IsEmpty())\r
+                       sRet += _T("*");\r
+               sRet += it->GetWinPathString();\r
+       }\r
+       return sRet;\r
+}\r
+#endif // _MFC_VER\r
+\r
+bool \r
+CTGitPathList::AreAllPathsFilesInOneDirectory() const\r
+{\r
+       // Check if all the paths are files and in the same directory\r
+       PathVector::const_iterator it;\r
+       m_commonBaseDirectory.Reset();\r
+       for(it = m_paths.begin(); it != m_paths.end(); ++it)\r
+       {\r
+               if(it->IsDirectory())\r
+               {\r
+                       return false;\r
+               }\r
+               const CTGitPath& baseDirectory = it->GetDirectory();\r
+               if(m_commonBaseDirectory.IsEmpty())\r
+               {\r
+                       m_commonBaseDirectory = baseDirectory;\r
+               }\r
+               else if(!m_commonBaseDirectory.IsEquivalentTo(baseDirectory))\r
+               {\r
+                       // Different path\r
+                       m_commonBaseDirectory.Reset();\r
+                       return false;\r
+               }\r
+       }\r
+       return true;\r
+}\r
+\r
+CTGitPath CTGitPathList::GetCommonDirectory() const\r
+{\r
+       if (m_commonBaseDirectory.IsEmpty())\r
+       {\r
+               PathVector::const_iterator it;\r
+               for(it = m_paths.begin(); it != m_paths.end(); ++it)\r
+               {\r
+                       const CTGitPath& baseDirectory = it->GetDirectory();\r
+                       if(m_commonBaseDirectory.IsEmpty())\r
+                       {\r
+                               m_commonBaseDirectory = baseDirectory;\r
+                       }\r
+                       else if(!m_commonBaseDirectory.IsEquivalentTo(baseDirectory))\r
+                       {\r
+                               // Different path\r
+                               m_commonBaseDirectory.Reset();\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       // since we only checked strings, not paths,\r
+       // we have to make sure now that we really return a *path* here\r
+       PathVector::const_iterator iter;\r
+       for(iter = m_paths.begin(); iter != m_paths.end(); ++iter)\r
+       {\r
+               if (!m_commonBaseDirectory.IsAncestorOf(*iter))\r
+               {\r
+                       m_commonBaseDirectory = m_commonBaseDirectory.GetContainingDirectory();\r
+                       break;\r
+               }\r
+       }       \r
+       return m_commonBaseDirectory;\r
+}\r
+\r
+CTGitPath CTGitPathList::GetCommonRoot() const\r
+{\r
+       PathVector::const_iterator it;\r
+       CString sRoot, sTempRoot;\r
+       bool bEqual = true;\r
+\r
+       if (GetCount() == 1)\r
+               return m_paths[0];\r
+\r
+       int backSlashPos = 0;\r
+       int searchStartPos = 0;\r
+       while (bEqual)\r
+       {\r
+               for (it = m_paths.begin(); it != m_paths.end(); ++it)\r
+               {\r
+                       if (backSlashPos == 0)\r
+                       {\r
+                               backSlashPos = it->GetWinPathString().Find('\\', searchStartPos+1);\r
+                               if ((backSlashPos < 0)&&(searchStartPos != it->GetWinPathString().GetLength()))\r
+                                       backSlashPos = it->GetWinPathString().GetLength();\r
+                       }\r
+                       else if (it->GetWinPathString().Find('\\', searchStartPos+1) != backSlashPos)\r
+                       {\r
+                               if (it->GetWinPathString().Find('\\', searchStartPos+1) < 0)\r
+                               {\r
+                                       if (it->GetWinPathString().GetLength() != backSlashPos)\r
+                                       {\r
+                                               bEqual = false;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               else\r
+                               {\r
+                                       bEqual = false;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if (backSlashPos < 0)\r
+                       {\r
+                               bEqual = false;\r
+                               break;\r
+                       }\r
+               }\r
+               if (bEqual == false)\r
+               {\r
+                       if (searchStartPos)\r
+                               sRoot = m_paths[0].GetWinPathString().Left(searchStartPos+1);\r
+               }\r
+               else\r
+               {\r
+                       searchStartPos = backSlashPos;\r
+               }\r
+               backSlashPos = 0;\r
+       }\r
+\r
+       return CTGitPath(sRoot.TrimRight('\\'));\r
+}\r
+\r
+void CTGitPathList::SortByPathname(bool bReverse /*= false*/)\r
+{\r
+       std::sort(m_paths.begin(), m_paths.end());\r
+       if (bReverse)\r
+               std::reverse(m_paths.begin(), m_paths.end());\r
+}\r
+\r
+void CTGitPathList::DeleteAllFiles(bool bTrash)\r
+{\r
+       PathVector::const_iterator it;\r
+       if (bTrash)\r
+       {\r
+               SortByPathname();\r
+               CString sPaths;\r
+               for (it = m_paths.begin(); it != m_paths.end(); ++it)\r
+               {\r
+                       if ((it->Exists())&&(!it->IsDirectory()))\r
+                       {\r
+                               ::SetFileAttributes(it->GetWinPath(), FILE_ATTRIBUTE_NORMAL);\r
+                               sPaths += it->GetWinPath();\r
+                               sPaths += '\0';\r
+                       }\r
+               }\r
+               sPaths += '\0';\r
+               sPaths += '\0';\r
+               SHFILEOPSTRUCT shop = {0};\r
+               shop.wFunc = FO_DELETE;\r
+               shop.pFrom = (LPCTSTR)sPaths;\r
+               shop.fFlags = FOF_ALLOWUNDO|FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT;\r
+               SHFileOperation(&shop);\r
+       }\r
+       else\r
+       {\r
+               for (it = m_paths.begin(); it != m_paths.end(); ++it)\r
+               {\r
+                       if (!it->IsDirectory())\r
+                       {\r
+                               ::SetFileAttributes(it->GetWinPath(), FILE_ATTRIBUTE_NORMAL);\r
+                               ::DeleteFile(it->GetWinPath());\r
+                       }\r
+               }\r
+       }\r
+       Clear();\r
+}\r
+\r
+void CTGitPathList::RemoveDuplicates()\r
+{\r
+       SortByPathname();\r
+       // Remove the duplicates\r
+       // (Unique moves them to the end of the vector, then erase chops them off)\r
+       m_paths.erase(std::unique(m_paths.begin(), m_paths.end(), &CTGitPath::PredLeftEquivalentToRight), m_paths.end());\r
+}\r
+\r
+void CTGitPathList::RemoveAdminPaths()\r
+{\r
+       PathVector::iterator it;\r
+       for(it = m_paths.begin(); it != m_paths.end(); )\r
+       {\r
+               if (it->IsAdminDir())\r
+               {\r
+                       m_paths.erase(it);\r
+                       it = m_paths.begin();\r
+               }\r
+               else\r
+                       ++it;\r
+       }\r
+}\r
+\r
+void CTGitPathList::RemovePath(const CTGitPath& path)\r
+{\r
+       PathVector::iterator it;\r
+       for(it = m_paths.begin(); it != m_paths.end(); ++it)\r
+       {\r
+               if (it->IsEquivalentTo(path))\r
+               {\r
+                       m_paths.erase(it);\r
+                       return;\r
+               }\r
+       }\r
+}\r
+\r
+void CTGitPathList::RemoveChildren()\r
+{\r
+       SortByPathname();\r
+       m_paths.erase(std::unique(m_paths.begin(), m_paths.end(), &CTGitPath::CheckChild), m_paths.end());\r
+}\r
+\r
+bool CTGitPathList::IsEqual(const CTGitPathList& list)\r
+{\r
+       if (list.GetCount() != GetCount())\r
+               return false;\r
+       for (int i=0; i<list.GetCount(); ++i)\r
+       {\r
+               if (!list[i].IsEquivalentTo(m_paths[i]))\r
+                       return false;\r
+       }\r
+       return true;\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////////\r
+#if 0\r
+apr_array_header_t * CTGitPathList::MakePathArray (apr_pool_t *pool) const\r
+{\r
+       apr_array_header_t *targets = apr_array_make (pool, GetCount(), sizeof(const char *));\r
+\r
+       for(int nItem = 0; nItem < GetCount(); nItem++)\r
+       {\r
+               const char * target = m_paths[nItem].GetGitApiPath(pool);\r
+               (*((const char **) apr_array_push (targets))) = target;\r
+       }\r
+\r
+       return targets;\r
+}\r
+#endif\r
+//////////////////////////////////////////////////////////////////////////\r
+\r
+#if 0\r
+#if defined(_DEBUG)\r
+// Some test cases for these classes\r
+static class CTGitPathTests\r
+{\r
+public:\r
+       CTGitPathTests()\r
+       {\r
+               apr_initialize();\r
+               pool = svn_pool_create(NULL);\r
+               GetDirectoryTest();\r
+               AdminDirTest();\r
+               SortTest();\r
+               RawAppendTest();\r
+               PathAppendTest();\r
+               RemoveDuplicatesTest();\r
+               RemoveChildrenTest();\r
+               ContainingDirectoryTest();\r
+               AncestorTest();\r
+               SubversionPathTest();\r
+               GetCommonRootTest();\r
+#if defined(_MFC_VER)\r
+               ValidPathAndUrlTest();\r
+               ListLoadingTest();\r
+#endif\r
+               apr_terminate();\r
+       }\r
+\r
+private:\r
+//     apr_pool_t * pool;\r
+       void GetDirectoryTest()\r
+       {\r
+               // Bit tricky, this test, because we need to know something about the file\r
+               // layout on the machine which is running the test\r
+               TCHAR winDir[MAX_PATH+1];\r
+               GetWindowsDirectory(winDir, MAX_PATH);\r
+               CString sWinDir(winDir);\r
+\r
+               CTGitPath testPath;\r
+               // This is a file which we know will always be there\r
+               testPath.SetFromUnknown(sWinDir + _T("\\win.ini"));\r
+               ATLASSERT(!testPath.IsDirectory());\r
+               ATLASSERT(testPath.GetDirectory().GetWinPathString() == sWinDir);\r
+               ATLASSERT(testPath.GetContainingDirectory().GetWinPathString() == sWinDir);\r
+\r
+               // Now do the test on the win directory itself - It's hard to be sure about the containing directory\r
+               // but we know it must be different to the directory itself\r
+               testPath.SetFromUnknown(sWinDir);\r
+               ATLASSERT(testPath.IsDirectory());\r
+               ATLASSERT(testPath.GetDirectory().GetWinPathString() == sWinDir);\r
+               ATLASSERT(testPath.GetContainingDirectory().GetWinPathString() != sWinDir);\r
+               ATLASSERT(testPath.GetContainingDirectory().GetWinPathString().GetLength() < sWinDir.GetLength());\r
+\r
+               // Try a root path\r
+               testPath.SetFromUnknown(_T("C:\\"));\r
+               ATLASSERT(testPath.IsDirectory());\r
+               ATLASSERT(testPath.GetDirectory().GetWinPathString().CompareNoCase(_T("C:\\"))==0);\r
+               ATLASSERT(testPath.GetContainingDirectory().IsEmpty());\r
+               // Try a root UNC path\r
+               testPath.SetFromUnknown(_T("\\MYSTATION"));\r
+               ATLASSERT(testPath.GetContainingDirectory().IsEmpty());\r
+       }\r
+\r
+       void AdminDirTest()\r
+       {\r
+               CTGitPath testPath;\r
+               testPath.SetFromUnknown(_T("c:\\.svndir"));\r
+               ATLASSERT(!testPath.IsAdminDir());\r
+               testPath.SetFromUnknown(_T("c:\\test.svn"));\r
+               ATLASSERT(!testPath.IsAdminDir());\r
+               testPath.SetFromUnknown(_T("c:\\.svn"));\r
+               ATLASSERT(testPath.IsAdminDir());\r
+               testPath.SetFromUnknown(_T("c:\\.svndir\\test"));\r
+               ATLASSERT(!testPath.IsAdminDir());\r
+               testPath.SetFromUnknown(_T("c:\\.svn\\test"));\r
+               ATLASSERT(testPath.IsAdminDir());\r
+               \r
+               CTGitPathList pathList;\r
+               pathList.AddPath(CTGitPath(_T("c:\\.svndir")));\r
+               pathList.AddPath(CTGitPath(_T("c:\\.svn")));\r
+               pathList.AddPath(CTGitPath(_T("c:\\.svn\\test")));\r
+               pathList.AddPath(CTGitPath(_T("c:\\test")));\r
+               pathList.RemoveAdminPaths();\r
+               ATLASSERT(pathList.GetCount()==2);\r
+               pathList.Clear();\r
+               pathList.AddPath(CTGitPath(_T("c:\\test")));\r
+               pathList.RemoveAdminPaths();\r
+               ATLASSERT(pathList.GetCount()==1);\r
+       }\r
+       \r
+       void SortTest()\r
+       {\r
+               CTGitPathList testList;\r
+               CTGitPath testPath;\r
+               testPath.SetFromUnknown(_T("c:/Z"));\r
+               testList.AddPath(testPath);\r
+               testPath.SetFromUnknown(_T("c:/B"));\r
+               testList.AddPath(testPath);\r
+               testPath.SetFromUnknown(_T("c:\\a"));\r
+               testList.AddPath(testPath);\r
+               testPath.SetFromUnknown(_T("c:/Test"));\r
+               testList.AddPath(testPath);\r
+\r
+               testList.SortByPathname();\r
+\r
+               ATLASSERT(testList[0].GetWinPathString() == _T("c:\\a"));\r
+               ATLASSERT(testList[1].GetWinPathString() == _T("c:\\B"));\r
+               ATLASSERT(testList[2].GetWinPathString() == _T("c:\\Test"));\r
+               ATLASSERT(testList[3].GetWinPathString() == _T("c:\\Z"));\r
+       }\r
+\r
+       void RawAppendTest()\r
+       {\r
+               CTGitPath testPath(_T("c:/test/"));\r
+               testPath.AppendRawString(_T("/Hello"));\r
+               ATLASSERT(testPath.GetWinPathString() == _T("c:\\test\\Hello"));\r
+\r
+               testPath.AppendRawString(_T("\\T2"));\r
+               ATLASSERT(testPath.GetWinPathString() == _T("c:\\test\\Hello\\T2"));\r
+\r
+               CTGitPath testFilePath(_T("C:\\windows\\win.ini"));\r
+               CTGitPath testBasePath(_T("c:/temp/myfile.txt"));\r
+               testBasePath.AppendRawString(testFilePath.GetFileExtension());\r
+               ATLASSERT(testBasePath.GetWinPathString() == _T("c:\\temp\\myfile.txt.ini"));\r
+       }\r
+\r
+       void PathAppendTest()\r
+       {\r
+               CTGitPath testPath(_T("c:/test/"));\r
+               testPath.AppendPathString(_T("/Hello"));\r
+               ATLASSERT(testPath.GetWinPathString() == _T("c:\\test\\Hello"));\r
+\r
+               testPath.AppendPathString(_T("T2"));\r
+               ATLASSERT(testPath.GetWinPathString() == _T("c:\\test\\Hello\\T2"));\r
+\r
+               CTGitPath testFilePath(_T("C:\\windows\\win.ini"));\r
+               CTGitPath testBasePath(_T("c:/temp/myfile.txt"));\r
+               // You wouldn't want to do this in real life - you'd use append-raw\r
+               testBasePath.AppendPathString(testFilePath.GetFileExtension());\r
+               ATLASSERT(testBasePath.GetWinPathString() == _T("c:\\temp\\myfile.txt\\.ini"));\r
+       }\r
+\r
+       void RemoveDuplicatesTest()\r
+       {\r
+               CTGitPathList list;\r
+               list.AddPath(CTGitPath(_T("Z")));\r
+               list.AddPath(CTGitPath(_T("A")));\r
+               list.AddPath(CTGitPath(_T("E")));\r
+               list.AddPath(CTGitPath(_T("E")));\r
+\r
+               ATLASSERT(list[2].IsEquivalentTo(list[3]));\r
+               ATLASSERT(list[2]==list[3]);\r
+               \r
+               ATLASSERT(list.GetCount() == 4);\r
+\r
+               list.RemoveDuplicates();\r
+\r
+               ATLASSERT(list.GetCount() == 3);\r
+\r
+               ATLASSERT(list[0].GetWinPathString() == _T("A"));\r
+               ATLASSERT(list[1].GetWinPathString().Compare(_T("E")) == 0);\r
+               ATLASSERT(list[2].GetWinPathString() == _T("Z"));\r
+       }\r
+       \r
+       void RemoveChildrenTest()\r
+       {\r
+               CTGitPathList list;\r
+               list.AddPath(CTGitPath(_T("c:\\test")));\r
+               list.AddPath(CTGitPath(_T("c:\\test\\file")));\r
+               list.AddPath(CTGitPath(_T("c:\\testfile")));\r
+               list.AddPath(CTGitPath(_T("c:\\parent")));\r
+               list.AddPath(CTGitPath(_T("c:\\parent\\child")));\r
+               list.AddPath(CTGitPath(_T("c:\\parent\\child1")));\r
+               list.AddPath(CTGitPath(_T("c:\\parent\\child2")));\r
+               \r
+               ATLASSERT(list.GetCount() == 7);\r
+\r
+               list.RemoveChildren();\r
+               \r
+               ATLTRACE("count = %d\n", list.GetCount());\r
+               ATLASSERT(list.GetCount() == 3);\r
+\r
+               list.SortByPathname();\r
+\r
+               ATLASSERT(list[0].GetWinPathString().Compare(_T("c:\\parent")) == 0);\r
+               ATLASSERT(list[1].GetWinPathString().Compare(_T("c:\\test")) == 0);\r
+               ATLASSERT(list[2].GetWinPathString().Compare(_T("c:\\testfile")) == 0);\r
+       }\r
+\r
+#if defined(_MFC_VER)\r
+       void ListLoadingTest()\r
+       {\r
+               TCHAR buf[MAX_PATH];\r
+               GetCurrentDirectory(MAX_PATH, buf);\r
+               CString sPathList(_T("Path1*c:\\path2 with spaces and stuff*\\funnypath\\*"));\r
+               CTGitPathList testList;\r
+               testList.LoadFromAsteriskSeparatedString(sPathList);\r
+\r
+               ATLASSERT(testList.GetCount() == 3);\r
+               ATLASSERT(testList[0].GetWinPathString() == CString(buf) + _T("\\Path1"));\r
+               ATLASSERT(testList[1].GetWinPathString() == _T("c:\\path2 with spaces and stuff"));\r
+               ATLASSERT(testList[2].GetWinPathString() == _T("\\funnypath"));\r
+               \r
+               ATLASSERT(testList.GetCommonRoot().GetWinPathString() == _T(""));\r
+               testList.Clear();\r
+               sPathList = _T("c:\\path2 with spaces and stuff*c:\\funnypath\\*");\r
+               testList.LoadFromAsteriskSeparatedString(sPathList);\r
+               ATLASSERT(testList.GetCommonRoot().GetWinPathString() == _T("c:\\"));\r
+       }\r
+#endif \r
+\r
+       void ContainingDirectoryTest()\r
+       {\r
+\r
+               CTGitPath testPath;\r
+               testPath.SetFromWin(_T("c:\\a\\b\\c\\d\\e"));\r
+               CTGitPath dir;\r
+               dir = testPath.GetContainingDirectory();\r
+               ATLASSERT(dir.GetWinPathString() == _T("c:\\a\\b\\c\\d"));\r
+               dir = dir.GetContainingDirectory();\r
+               ATLASSERT(dir.GetWinPathString() == _T("c:\\a\\b\\c"));\r
+               dir = dir.GetContainingDirectory();\r
+               ATLASSERT(dir.GetWinPathString() == _T("c:\\a\\b"));\r
+               dir = dir.GetContainingDirectory();\r
+               ATLASSERT(dir.GetWinPathString() == _T("c:\\a"));\r
+               dir = dir.GetContainingDirectory();\r
+               ATLASSERT(dir.GetWinPathString() == _T("c:\\"));\r
+               dir = dir.GetContainingDirectory();\r
+               ATLASSERT(dir.IsEmpty());\r
+               ATLASSERT(dir.GetWinPathString() == _T(""));\r
+       }\r
+       \r
+       void AncestorTest()\r
+       {\r
+               CTGitPath testPath;\r
+               testPath.SetFromWin(_T("c:\\windows"));\r
+               ATLASSERT(testPath.IsAncestorOf(CTGitPath(_T("c:\\")))==false);\r
+               ATLASSERT(testPath.IsAncestorOf(CTGitPath(_T("c:\\windows"))));\r
+               ATLASSERT(testPath.IsAncestorOf(CTGitPath(_T("c:\\windowsdummy")))==false);\r
+               ATLASSERT(testPath.IsAncestorOf(CTGitPath(_T("c:\\windows\\test.txt"))));\r
+               ATLASSERT(testPath.IsAncestorOf(CTGitPath(_T("c:\\windows\\system32\\test.txt"))));\r
+       }\r
+\r
+       void SubversionPathTest()\r
+       {\r
+               CTGitPath testPath;\r
+               testPath.SetFromWin(_T("c:\\"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "c:") == 0);\r
+               testPath.SetFromWin(_T("c:\\folder"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "c:/folder") == 0);\r
+               testPath.SetFromWin(_T("c:\\a\\b\\c\\d\\e"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "c:/a/b/c/d/e") == 0);\r
+               testPath.SetFromUnknown(_T("http://testing/"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "http://testing") == 0);\r
+               testPath.SetFromGit(NULL);\r
+               ATLASSERT(strlen(testPath.GetGitApiPath(pool))==0);\r
+#if defined(_MFC_VER)\r
+               testPath.SetFromUnknown(_T("http://testing again"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "http://testing%20again") == 0);\r
+               testPath.SetFromUnknown(_T("http://testing%20again"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "http://testing%20again") == 0);\r
+               testPath.SetFromUnknown(_T("http://testing special chars \344\366\374"));\r
+               ATLASSERT(strcmp(testPath.GetGitApiPath(pool), "http://testing%20special%20chars%20%c3%a4%c3%b6%c3%bc") == 0);          \r
+#endif\r
+       }\r
+\r
+       void GetCommonRootTest()\r
+       {\r
+               CTGitPath pathA (_T("C:\\Development\\LogDlg.cpp"));\r
+               CTGitPath pathB (_T("C:\\Development\\LogDlg.h"));\r
+               CTGitPath pathC (_T("C:\\Development\\SomeDir\\LogDlg.h"));\r
+               \r
+               CTGitPathList list;\r
+               list.AddPath(pathA);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("C:\\Development\\LogDlg.cpp"))==0);\r
+               list.AddPath(pathB);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("C:\\Development"))==0);\r
+               list.AddPath(pathC);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("C:\\Development"))==0);\r
+#ifdef _MFC_VER\r
+               list.Clear();\r
+               CString sPathList = _T("D:\\Development\\StExBar\\StExBar\\src\\setup\\Setup64.wxs*D:\\Development\\StExBar\\StExBar\\src\\setup\\Setup.wxs*D:\\Development\\StExBar\\SKTimeStamp\\src\\setup\\Setup.wxs*D:\\Development\\StExBar\\SKTimeStamp\\src\\setup\\Setup64.wxs");\r
+               list.LoadFromAsteriskSeparatedString(sPathList);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("D:\\Development\\StExBar"))==0);\r
+\r
+               list.Clear();\r
+               sPathList = _T("c:\\windows\\explorer.exe*c:\\windows");\r
+               list.LoadFromAsteriskSeparatedString(sPathList);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("c:\\windows"))==0);\r
+\r
+               list.Clear();\r
+               sPathList = _T("c:\\windows\\*c:\\windows");\r
+               list.LoadFromAsteriskSeparatedString(sPathList);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("c:\\windows"))==0);\r
+\r
+               list.Clear();\r
+               sPathList = _T("c:\\windows\\system32*c:\\windows\\system");\r
+               list.LoadFromAsteriskSeparatedString(sPathList);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("c:\\windows"))==0);\r
+\r
+               list.Clear();\r
+               sPathList = _T("c:\\windowsdummy*c:\\windows");\r
+               list.LoadFromAsteriskSeparatedString(sPathList);\r
+               ATLASSERT(list.GetCommonRoot().GetWinPathString().CompareNoCase(_T("c:\\"))==0);\r
+#endif\r
+       }\r
+       \r
+       void ValidPathAndUrlTest()\r
+       {\r
+               CTGitPath testPath;\r
+               testPath.SetFromWin(_T("c:\\a\\b\\c.test.txt"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("D:\\.Net\\SpindleSearch\\"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\test folder\\file"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\folder\\"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\ext.ext.ext\\ext.ext.ext.ext"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\.svn"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\com\\file"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\test\\conf"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\LPT"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\test\\LPT"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\com1test"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("\\\\?\\c:\\test\\com1test"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+\r
+               testPath.SetFromWin(_T("\\\\Share\\filename"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("\\\\Share\\filename.extension"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("\\\\Share\\.svn"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+\r
+               // now the negative tests\r
+               testPath.SetFromWin(_T("c:\\test:folder"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\file<name"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\something*else"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\folder\\file?nofile"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\ext.>ension"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\com1\\filename"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\com1"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("c:\\com1\\AuX"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+\r
+               testPath.SetFromWin(_T("\\\\Share\\lpt9\\filename"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("\\\\Share\\prn"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromWin(_T("\\\\Share\\NUL"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               \r
+               // now come some URL tests\r
+               testPath.SetFromGit(_T("http://myserver.com/repos/trunk"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("https://myserver.com/repos/trunk/file%20with%20spaces"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("svn://myserver.com/repos/trunk/file with spaces"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("svn+ssh://www.myserver.com/repos/trunk"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("http://localhost:90/repos/trunk"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("file:///C:/GitRepos/Tester/Proj1/tags/t2"));\r
+               ATLASSERT(testPath.IsValidOnWindows());\r
+               // and some negative URL tests\r
+               testPath.SetFromGit(_T("httpp://myserver.com/repos/trunk"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("https://myserver.com/rep:os/trunk/file%20with%20spaces"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("svn://myserver.com/rep<os/trunk/file with spaces"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("svn+ssh://www.myserver.com/repos/trunk/prn/"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               testPath.SetFromGit(_T("http://localhost:90/repos/trunk/com1"));\r
+               ATLASSERT(!testPath.IsValidOnWindows());\r
+               \r
+       }\r
+\r
+} TGitPathTestobject;\r
+#endif\r
+#endif\r
+\r
index e590eb8..3998185 100644 (file)
@@ -5,7 +5,8 @@ class CTGitPath
 public:\r
        CTGitPath(void);\r
        ~CTGitPath(void);\r
-       public:\r
+explicit CTGitPath(const CString& sUnknownPath);\r
+public:\r
        /**\r
         * Set the path as an UTF8 string with forward slashes\r
         */\r
index 28d449d..a4c642f 100644 (file)
@@ -155,7 +155,7 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)
     {\r
 //             apr_initialize();\r
 //             git_dso_initialize2();\r
-//             g_SVNAdminDir.Init();\r
+               g_GitAdminDir.Init();\r
                g_cAprInit++;\r
                \r
                CShellExtClassFactory *pcf = new CShellExtClassFactory(state);\r
index 5018b44..62c3505 100644 (file)
@@ -249,9 +249,9 @@ BEGIN
     IDS_MENUDESCREMOVE      "Deletes files / folders from version control"\r
     IDS_MENUUPDATEEXT       "&Update to revision..."\r
     IDS_MENUDESCUPDATEEXT   "Updates the working copy to a specific revision"\r
-    IDS_COLTITLESTATUS      "SVN Status"\r
-    IDS_COLDESCSTATUS       "Status of item in SVN"\r
-    IDS_COLTITLEREV         "SVN Revision"\r
+    IDS_COLTITLESTATUS      "Git Status"\r
+    IDS_COLDESCSTATUS       "Status of item in Git"\r
+    IDS_COLTITLEREV         "Git Revision"\r
     IDS_COLDESCREV          "Last saved revision of item"\r
 END\r
 \r
@@ -263,7 +263,7 @@ BEGIN
     IDS_MENUDESCIGNORE      "Adds the selected file(s) or the filemask to the 'ignore' list"\r
     IDS_STATUSINCOMPLETE    "incomplete"\r
     IDS_STATUSIGNORED       "ignored"\r
-    IDS_DROPCOPYMENU        "SVN Copy versioned item(s) here"\r
+    IDS_DROPCOPYMENU        "Git Copy versioned item(s) here"\r
     IDS_PROPWAITCANCEL      "Please wait while cancelling..."\r
     IDS_SETPROPTITLE        "Setting properties..."\r
     IDS_MENUREPOBROWSE      "&Repo-browser"\r
@@ -279,14 +279,14 @@ STRINGTABLE
 BEGIN\r
     IDS_MENUDIFF            "&Diff"\r
     IDS_MENUDESCDIFF        "Compares the file with the last committed revision to show you the changes you made"\r
-    IDS_DROPCOPYADDMENU     "SVN Copy and add files to this WC"\r
-    IDS_DROPMOVEMENU        "SVN Move versioned item(s) here"\r
+    IDS_DROPCOPYADDMENU     "Git Copy and add files to this WC"\r
+    IDS_DROPMOVEMENU        "Git Move versioned item(s) here"\r
     IDS_MENULOG             "Show &log"\r
     IDS_MENUDESCLOG         "Shows the log for the selected file / folder"\r
-    IDS_COLTITLEURL         "SVN URL"\r
-    IDS_COLDESCURL          "URL of Subversion items"\r
-    IDS_COLTITLESHORTURL    "SVN short URL"\r
-    IDS_COLDESCSHORTURL     "Short URL of Subversion items"\r
+    IDS_COLTITLEURL         "Git URL"\r
+    IDS_COLDESCURL          "URL of Git items"\r
+    IDS_COLTITLESHORTURL    "Git short URL"\r
+    IDS_COLDESCSHORTURL     "Short URL of Git items"\r
     IDS_MENUCONFLICT        "&Edit conflicts"\r
     IDS_MENUDESCCONFLICT    "Launches the external diff / merge program to solve the conflicts"\r
     IDS_MENURELOCATE        "Relo&cate..."\r
@@ -305,10 +305,10 @@ BEGIN
     IDS_MENUDESCUNDOADD     "Reverts an addition to version control"\r
     IDS_MENUPREVDIFF        "&Diff with previous version"\r
     IDS_MENUDESCPREVDIFF    "Diffs the working copy file with the one before the last commit."\r
-    IDS_COLTITLEMIMETYPE    "SVN mime-type"\r
+    IDS_COLTITLEMIMETYPE    "Git mime-type"\r
     IDS_COLDESCMIMETYPE     "Shows the mime type of the versioned file"\r
-    IDS_DROPEXPORTMENU      "SVN Export versioned items here"\r
-    IDS_DROPEXPORTEXTENDEDMENU "SVN Export all items here"\r
+    IDS_DROPEXPORTMENU      "Git Export versioned items here"\r
+    IDS_DROPEXPORTEXTENDEDMENU "Git Export all items here"\r
     IDS_MENUIGNOREMULTIPLEMASK "Ignore items by &extension"\r
 END\r
 \r
@@ -328,10 +328,10 @@ END
 \r
 STRINGTABLE \r
 BEGIN\r
-    IDS_DROPMOVERENAMEMENU  "SVN Move and rename versioned item here"\r
+    IDS_DROPMOVERENAMEMENU  "Git Move and rename versioned item here"\r
     IDS_MENUPROPERTIES      "Properties"\r
     IDS_MENUDESCPROPERTIES  "Manage Subversion properties"\r
-    IDS_COLTITLEEOLSTYLE    "SVN eol-style"\r
+    IDS_COLTITLEEOLSTYLE    "Git eol-style"\r
     IDS_COLDESCEOLSTYLE     "Shows the eol-style property value"\r
     IDS_MENUURLDIFF         "&Diff with URL"\r
     IDS_MENUDESCURLDIFF     "Compares the selected file with a file in the repository"\r
@@ -351,10 +351,10 @@ BEGIN
     IDS_MENUDESC_UNLOCKFORCE \r
                             "Releases locks even if you're not the owner of the locks (breaks them)."\r
     IDS_MENU_LOCKFORCE      "Steal loc&k"\r
-    IDS_COLTITLEOWNER       "SVN Local lock owner"\r
+    IDS_COLTITLEOWNER       "Git Local lock owner"\r
     IDS_COLDESCOWNER        "The user who owns the lock of the file"\r
-    IDS_DROPCOPYRENAMEMENU  "SVN Copy and rename versioned item here"\r
-    IDS_COLTITLEAUTHOR      "SVN Author"\r
+    IDS_DROPCOPYRENAMEMENU  "Git Copy and rename versioned item here"\r
+    IDS_COLTITLEAUTHOR      "Git Author"\r
     IDS_COLDESCAUTHOR       "The user who did the last commit"\r
     IDS_FILEPROPONFOLDER    "You can't set this property on folders, only on files!\nIf you want to set it on all files within that folder,\nyou must activate the 'recursive' checkbox."\r
     IDS_PROPSNOTSAVED       "You have modified properties without saving them first.\nDo you want to save them now?"\r