Changed code to make the subversion plug-ins compatible with the new generation working copy meta-data format. 5_2_x

Sun, 22 Jan 2012 19:27:40 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sun, 22 Jan 2012 19:27:40 +0100
branch
5_2_x
changeset 1577
f41d8406c219
parent 1575
3d8ba641a83d
child 1578
bf93c2a874e1

Changed code to make the subversion plug-ins compatible with the new generation working copy meta-data format.
(transplanted from 72e5b4b8bad7cb3092cfa78fa303e21f0d55c3f7)

Documentation/Help/source.qch file | annotate | diff | comparison | revisions
Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html file | annotate | diff | comparison | revisions
Documentation/Source/eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsPySvn/SvnDialog.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsPySvn/subversion.py file | annotate | diff | comparison | revisions
Plugins/VcsPlugins/vcsSubversion/subversion.py file | annotate | diff | comparison | revisions
changelog file | annotate | diff | comparison | revisions
Binary file Documentation/Help/source.qch has changed
--- a/Documentation/Help/source.qhp	Sat Jan 21 17:27:30 2012 +0100
+++ b/Documentation/Help/source.qhp	Sun Jan 22 19:27:40 2012 +0100
@@ -8280,8 +8280,16 @@
       <keyword name="Subversion (Constructor)" id="Subversion (Constructor)" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__init__" />
       <keyword name="Subversion.__svnURL" id="Subversion.__svnURL" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__svnURL" />
       <keyword name="Subversion.__svnURL" id="Subversion.__svnURL" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__svnURL" />
+      <keyword name="Subversion.__vcsAllRegisteredStates_wc" id="Subversion.__vcsAllRegisteredStates_wc" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__vcsAllRegisteredStates_wc" />
+      <keyword name="Subversion.__vcsAllRegisteredStates_wc" id="Subversion.__vcsAllRegisteredStates_wc" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__vcsAllRegisteredStates_wc" />
+      <keyword name="Subversion.__vcsAllRegisteredStates_wcng" id="Subversion.__vcsAllRegisteredStates_wcng" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__vcsAllRegisteredStates_wcng" />
+      <keyword name="Subversion.__vcsAllRegisteredStates_wcng" id="Subversion.__vcsAllRegisteredStates_wcng" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__vcsAllRegisteredStates_wcng" />
       <keyword name="Subversion.__vcsCommit_Step2" id="Subversion.__vcsCommit_Step2" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__vcsCommit_Step2" />
       <keyword name="Subversion.__vcsCommit_Step2" id="Subversion.__vcsCommit_Step2" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__vcsCommit_Step2" />
+      <keyword name="Subversion.__vcsRegisteredState_wc" id="Subversion.__vcsRegisteredState_wc" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__vcsRegisteredState_wc" />
+      <keyword name="Subversion.__vcsRegisteredState_wc" id="Subversion.__vcsRegisteredState_wc" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__vcsRegisteredState_wc" />
+      <keyword name="Subversion.__vcsRegisteredState_wcng" id="Subversion.__vcsRegisteredState_wcng" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.__vcsRegisteredState_wcng" />
+      <keyword name="Subversion.__vcsRegisteredState_wcng" id="Subversion.__vcsRegisteredState_wcng" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion.__vcsRegisteredState_wcng" />
       <keyword name="Subversion._createStatusMonitorThread" id="Subversion._createStatusMonitorThread" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion._createStatusMonitorThread" />
       <keyword name="Subversion._createStatusMonitorThread" id="Subversion._createStatusMonitorThread" ref="eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html#Subversion._createStatusMonitorThread" />
       <keyword name="Subversion.clearStatusCache" id="Subversion.clearStatusCache" ref="eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html#Subversion.clearStatusCache" />
--- a/Documentation/Source/eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html	Sat Jan 21 17:27:30 2012 +0100
+++ b/Documentation/Source/eric5.Plugins.VcsPlugins.vcsPySvn.subversion.html	Sun Jan 22 19:27:40 2012 +0100
@@ -70,9 +70,21 @@
 <td><a href="#Subversion.__svnURL">__svnURL</a></td>
 <td>Private method to format a url for subversion.</td>
 </tr><tr>
+<td><a href="#Subversion.__vcsAllRegisteredStates_wc">__vcsAllRegisteredStates_wc</a></td>
+<td>Private method used to get the registered states of a number of files in the vcs.</td>
+</tr><tr>
+<td><a href="#Subversion.__vcsAllRegisteredStates_wcng">__vcsAllRegisteredStates_wcng</a></td>
+<td>Private method used to get the registered states of a number of files in the vcs.</td>
+</tr><tr>
 <td><a href="#Subversion.__vcsCommit_Step2">__vcsCommit_Step2</a></td>
 <td>Private slot performing the second step of the commit action.</td>
 </tr><tr>
+<td><a href="#Subversion.__vcsRegisteredState_wc">__vcsRegisteredState_wc</a></td>
+<td>Private method used to get the registered state of a file in the vcs.</td>
+</tr><tr>
+<td><a href="#Subversion.__vcsRegisteredState_wcng">__vcsRegisteredState_wcng</a></td>
+<td>Private method used to get the registered state of a file in the vcs.</td>
+</tr><tr>
 <td><a href="#Subversion._createStatusMonitorThread">_createStatusMonitorThread</a></td>
 <td>Protected method to create an instance of the VCS status monitor thread.</td>
 </tr><tr>
@@ -271,12 +283,106 @@
 <dd>
 properly formated url for subversion (string)
 </dd>
+</dl><a NAME="Subversion.__vcsAllRegisteredStates_wc" ID="Subversion.__vcsAllRegisteredStates_wc"></a>
+<h4>Subversion.__vcsAllRegisteredStates_wc</h4>
+<b>__vcsAllRegisteredStates_wc</b>(<i>names, dname, shortcut = True</i>)
+<p>
+        Private method used to get the registered states of a number of files in the vcs.
+</p><p>
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+</p><p>
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+</p><dl>
+<dt><i>names</i></dt>
+<dd>
+dictionary with all filenames to be checked as keys
+</dd><dt><i>dname</i></dt>
+<dd>
+directory to check in (string)
+</dd><dt><i>shortcut</i></dt>
+<dd>
+flag indicating a shortcut should be taken (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+the received dictionary completed with a combination of
+            canBeCommited and canBeAdded or None in order to signal an error
+</dd>
+</dl><a NAME="Subversion.__vcsAllRegisteredStates_wcng" ID="Subversion.__vcsAllRegisteredStates_wcng"></a>
+<h4>Subversion.__vcsAllRegisteredStates_wcng</h4>
+<b>__vcsAllRegisteredStates_wcng</b>(<i>names, dname, shortcut = True</i>)
+<p>
+        Private method used to get the registered states of a number of files in the vcs.
+</p><p>
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+</p><p>
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+</p><dl>
+<dt><i>names</i></dt>
+<dd>
+dictionary with all filenames to be checked as keys
+</dd><dt><i>dname</i></dt>
+<dd>
+directory to check in (string)
+</dd><dt><i>shortcut</i></dt>
+<dd>
+flag indicating a shortcut should be taken (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+the received dictionary completed with a combination of
+            canBeCommited and canBeAdded or None in order to signal an error
+</dd>
 </dl><a NAME="Subversion.__vcsCommit_Step2" ID="Subversion.__vcsCommit_Step2"></a>
 <h4>Subversion.__vcsCommit_Step2</h4>
 <b>__vcsCommit_Step2</b>(<i></i>)
 <p>
         Private slot performing the second step of the commit action.
-</p><a NAME="Subversion._createStatusMonitorThread" ID="Subversion._createStatusMonitorThread"></a>
+</p><a NAME="Subversion.__vcsRegisteredState_wc" ID="Subversion.__vcsRegisteredState_wc"></a>
+<h4>Subversion.__vcsRegisteredState_wc</h4>
+<b>__vcsRegisteredState_wc</b>(<i>name</i>)
+<p>
+        Private method used to get the registered state of a file in the vcs.
+</p><p>
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+</p><dl>
+<dt><i>name</i></dt>
+<dd>
+filename to check (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+a combination of canBeCommited and canBeAdded
+</dd>
+</dl><a NAME="Subversion.__vcsRegisteredState_wcng" ID="Subversion.__vcsRegisteredState_wcng"></a>
+<h4>Subversion.__vcsRegisteredState_wcng</h4>
+<b>__vcsRegisteredState_wcng</b>(<i>name</i>)
+<p>
+        Private method used to get the registered state of a file in the vcs.
+</p><p>
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+</p><dl>
+<dt><i>name</i></dt>
+<dd>
+filename to check (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+a combination of canBeCommited and canBeAdded
+</dd>
+</dl><a NAME="Subversion._createStatusMonitorThread" ID="Subversion._createStatusMonitorThread"></a>
 <h4>Subversion._createStatusMonitorThread</h4>
 <b>_createStatusMonitorThread</b>(<i>interval, project</i>)
 <p>
--- a/Documentation/Source/eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html	Sat Jan 21 17:27:30 2012 +0100
+++ b/Documentation/Source/eric5.Plugins.VcsPlugins.vcsSubversion.subversion.html	Sun Jan 22 19:27:40 2012 +0100
@@ -70,9 +70,21 @@
 <td><a href="#Subversion.__svnURL">__svnURL</a></td>
 <td>Private method to format a url for subversion.</td>
 </tr><tr>
+<td><a href="#Subversion.__vcsAllRegisteredStates_wc">__vcsAllRegisteredStates_wc</a></td>
+<td>Private method used to get the registered states of a number of files in the vcs.</td>
+</tr><tr>
+<td><a href="#Subversion.__vcsAllRegisteredStates_wcng">__vcsAllRegisteredStates_wcng</a></td>
+<td>Private method used to get the registered states of a number of files in the vcs.</td>
+</tr><tr>
 <td><a href="#Subversion.__vcsCommit_Step2">__vcsCommit_Step2</a></td>
 <td>Private slot performing the second step of the commit action.</td>
 </tr><tr>
+<td><a href="#Subversion.__vcsRegisteredState_wc">__vcsRegisteredState_wc</a></td>
+<td>Private method used to get the registered state of a file in the vcs.</td>
+</tr><tr>
+<td><a href="#Subversion.__vcsRegisteredState_wcng">__vcsRegisteredState_wcng</a></td>
+<td>Private method used to get the registered state of a file in the vcs.</td>
+</tr><tr>
 <td><a href="#Subversion._createStatusMonitorThread">_createStatusMonitorThread</a></td>
 <td>Protected method to create an instance of the VCS status monitor thread.</td>
 </tr><tr>
@@ -265,12 +277,106 @@
 <dd>
 properly formated url for subversion (string)
 </dd>
+</dl><a NAME="Subversion.__vcsAllRegisteredStates_wc" ID="Subversion.__vcsAllRegisteredStates_wc"></a>
+<h4>Subversion.__vcsAllRegisteredStates_wc</h4>
+<b>__vcsAllRegisteredStates_wc</b>(<i>names, dname, shortcut = True</i>)
+<p>
+        Private method used to get the registered states of a number of files in the vcs.
+</p><p>
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+</p><p>
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+</p><dl>
+<dt><i>names</i></dt>
+<dd>
+dictionary with all filenames to be checked as keys
+</dd><dt><i>dname</i></dt>
+<dd>
+directory to check in (string)
+</dd><dt><i>shortcut</i></dt>
+<dd>
+flag indicating a shortcut should be taken (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+the received dictionary completed with a combination of
+            canBeCommited and canBeAdded or None in order to signal an error
+</dd>
+</dl><a NAME="Subversion.__vcsAllRegisteredStates_wcng" ID="Subversion.__vcsAllRegisteredStates_wcng"></a>
+<h4>Subversion.__vcsAllRegisteredStates_wcng</h4>
+<b>__vcsAllRegisteredStates_wcng</b>(<i>names, dname, shortcut = True</i>)
+<p>
+        Private method used to get the registered states of a number of files in the vcs.
+</p><p>
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+</p><p>
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+</p><dl>
+<dt><i>names</i></dt>
+<dd>
+dictionary with all filenames to be checked as keys
+</dd><dt><i>dname</i></dt>
+<dd>
+directory to check in (string)
+</dd><dt><i>shortcut</i></dt>
+<dd>
+flag indicating a shortcut should be taken (boolean)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+the received dictionary completed with a combination of
+            canBeCommited and canBeAdded or None in order to signal an error
+</dd>
 </dl><a NAME="Subversion.__vcsCommit_Step2" ID="Subversion.__vcsCommit_Step2"></a>
 <h4>Subversion.__vcsCommit_Step2</h4>
 <b>__vcsCommit_Step2</b>(<i></i>)
 <p>
         Private slot performing the second step of the commit action.
-</p><a NAME="Subversion._createStatusMonitorThread" ID="Subversion._createStatusMonitorThread"></a>
+</p><a NAME="Subversion.__vcsRegisteredState_wc" ID="Subversion.__vcsRegisteredState_wc"></a>
+<h4>Subversion.__vcsRegisteredState_wc</h4>
+<b>__vcsRegisteredState_wc</b>(<i>name</i>)
+<p>
+        Private method used to get the registered state of a file in the vcs.
+</p><p>
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+</p><dl>
+<dt><i>name</i></dt>
+<dd>
+filename to check (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+a combination of canBeCommited and canBeAdded
+</dd>
+</dl><a NAME="Subversion.__vcsRegisteredState_wcng" ID="Subversion.__vcsRegisteredState_wcng"></a>
+<h4>Subversion.__vcsRegisteredState_wcng</h4>
+<b>__vcsRegisteredState_wcng</b>(<i>name</i>)
+<p>
+        Private method used to get the registered state of a file in the vcs.
+</p><p>
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+</p><dl>
+<dt><i>name</i></dt>
+<dd>
+filename to check (string)
+</dd>
+</dl><dl>
+<dt>Returns:</dt>
+<dd>
+a combination of canBeCommited and canBeAdded
+</dd>
+</dl><a NAME="Subversion._createStatusMonitorThread" ID="Subversion._createStatusMonitorThread"></a>
 <h4>Subversion._createStatusMonitorThread</h4>
 <b>_createStatusMonitorThread</b>(<i>interval, project</i>)
 <p>
--- a/Plugins/VcsPlugins/vcsPySvn/SvnDialog.py	Sat Jan 21 17:27:30 2012 +0100
+++ b/Plugins/VcsPlugins/vcsPySvn/SvnDialog.py	Sun Jan 22 19:27:40 2012 +0100
@@ -75,6 +75,7 @@
         if eventDict["action"] == pysvn.wc_notify_action.update_completed:
             msg = self.trUtf8("Revision {0}.\n").format(eventDict["revision"].number)
         elif eventDict["path"] != "" and \
+             eventDict["action"] in svnNotifyActionMap and \
              svnNotifyActionMap[eventDict["action"]] is not None:
             mime = eventDict["mime_type"] == "application/octet-stream" and \
                 self.trUtf8(" (binary)") or ""
--- a/Plugins/VcsPlugins/vcsPySvn/subversion.py	Sat Jan 21 17:27:30 2012 +0100
+++ b/Plugins/VcsPlugins/vcsPySvn/subversion.py	Sun Jan 22 19:27:40 2012 +0100
@@ -129,6 +129,8 @@
         
         self.__commitData = {}
         self.__commitDialog = None
+        
+        self.__wcng = True      # assume new generation working copy metadata format
     
     def getPlugin(self):
         """
@@ -622,22 +624,49 @@
         names = []
         tree = []
         wdir = dname
-        while not os.path.exists(os.path.join(dname, self.adminDir)):
-            # add directories recursively, if they aren't in the repository already
-            tree.insert(-1, dname)
-            dname = os.path.split(dname)[0]
-            wdir = dname
+        if self.__wcng:
+            repodir = dname
+            while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                repodir = os.path.dirname(repodir)
+                if os.path.splitdrive(repodir)[1] == os.sep:
+                    return  # oops, project is not version controlled
+            while os.path.normcase(dname) != os.path.normcase(repodir) and \
+                  (os.path.normcase(dname) not in self.statusCache or \
+                   self.statusCache[os.path.normcase(dname)] == self.canBeAdded):
+                # add directories recursively, if they aren't in the repository already
+                tree.insert(-1, dname)
+                dname = os.path.dirname(dname)
+                wdir = dname
+        else:
+            while not os.path.exists(os.path.join(dname, self.adminDir)):
+                # add directories recursively, if they aren't in the repository already
+                tree.insert(-1, dname)
+                dname = os.path.dirname(dname)
+                wdir = dname
         names.extend(tree)
         
         if isinstance(name, list):
             tree2 = []
             for n in name:
-                d = os.path.split(n)[0]
-                while not os.path.exists(os.path.join(d, self.adminDir)):
-                    if d in tree2 + tree:
-                        break
-                    tree2.append(d)
-                    d = os.path.split(d)[0]
+                d = os.path.dirname(n)
+                if self.__wcng:
+                    repodir = d
+                    while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                        repodir = os.path.dirname(repodir)
+                        if os.path.splitdrive(repodir)[1] == os.sep:
+                            return  # oops, project is not version controlled
+                    while os.path.normcase(d) != os.path.normcase(repodir) and \
+                          (d not in tree2 + tree) and \
+                          (os.path.normcase(d) not in self.statusCache or \
+                           self.statusCache[os.path.normcase(d)] == self.canBeAdded):
+                        tree2.append(d)
+                        d = os.path.dirname(d)
+                else:
+                    while not os.path.exists(os.path.join(d, self.adminDir)):
+                        if d in tree2 + tree:
+                            break
+                        tree2.append(d)
+                        d = os.path.dirname(d)
             tree2.reverse()
             names.extend(tree2)
             names.extend(name)
@@ -693,22 +722,48 @@
         if isinstance(path, list):
             dname, fnames = self.splitPathList(path)
             for n in path:
-                d = os.path.split(n)[0]
-                while not os.path.exists(os.path.join(d, self.adminDir)):
-                    # add directories recursively,
-                    # if they aren't in the repository already
-                    if d in tree:
-                        break
-                    tree.append(d)
-                    d = os.path.split(d)[0]
+                d = os.path.dirname(n)
+                if self.__wcng:
+                    repodir = d
+                    while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                        repodir = os.path.dirname(repodir)
+                        if os.path.splitdrive(repodir)[1] == os.sep:
+                            return  # oops, project is not version controlled
+                    while os.path.normcase(d) != os.path.normcase(repodir) and \
+                          (d not in tree) and \
+                          (os.path.normcase(d) not in self.statusCache or \
+                           self.statusCache[os.path.normcase(d)] == self.canBeAdded):
+                        tree.append(d)
+                        d = os.path.dirname(d)
+                else:
+                    while not os.path.exists(os.path.join(d, self.adminDir)):
+                        # add directories recursively, 
+                        # if they aren't in the repository already
+                        if d in tree:
+                            break
+                        tree.append(d)
+                        d = os.path.dirname(d)
             tree.reverse()
         else:
             dname, fname = os.path.split(path)
-            while not os.path.exists(os.path.join(dname, self.adminDir)):
-                # add directories recursively,
-                # if they aren't in the repository already
-                tree.insert(-1, dname)
-                dname = os.path.split(dname)[0]
+            if self.__wcng:
+                repodir = dname
+                while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                    repodir = os.path.dirname(repodir)
+                    if os.path.splitdrive(repodir)[1] == os.sep:
+                        return  # oops, project is not version controlled
+                while os.path.normcase(dname) != os.path.normcase(repodir) and \
+                      (os.path.normcase(dname) not in self.statusCache or \
+                       self.statusCache[os.path.normcase(dname)] == self.canBeAdded):
+                    # add directories recursively, if they aren't in the repository already
+                    tree.insert(-1, dname)
+                    dname = os.path.dirname(dname)
+            else:
+                while not os.path.exists(os.path.join(dname, self.adminDir)):
+                    # add directories recursively,
+                    # if they aren't in the repository already
+                    tree.insert(-1, dname)
+                    dname = os.path.dirname(dname)
         if tree:
             self.vcsAdd(tree, True)
         
@@ -1218,6 +1273,50 @@
         @param name filename to check (string)
         @return a combination of canBeCommited and canBeAdded
         """
+        if self.__wcng:
+            return self.__vcsRegisteredState_wcng(name)
+        else:
+            return self.__vcsRegisteredState_wc(name)
+        
+    def __vcsRegisteredState_wcng(self, name):
+        """
+        Private method used to get the registered state of a file in the vcs.
+        
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+        
+        @param name filename to check (string)
+        @return a combination of canBeCommited and canBeAdded
+        """
+        if name.endswith(os.sep):
+            name = name[:-1]
+        name = os.path.normcase(name)
+        dname, fname = self.splitPath(name)
+        
+        if fname == '.' and os.path.isdir(os.path.join(dname, self.adminDir)):
+            return self.canBeCommitted
+        
+        if name in self.statusCache:
+            return self.statusCache[name]
+        
+        name = os.path.normcase(name)
+        states = { name : 0 }
+        states = self.vcsAllRegisteredStates(states, dname, False)
+        if states[name] == self.canBeCommitted:
+            return self.canBeCommitted
+        else:
+            return self.canBeAdded
+        
+    def __vcsRegisteredState_wc(self, name):
+        """
+        Private method used to get the registered state of a file in the vcs.
+        
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+        
+        @param name filename to check (string)
+        @return a combination of canBeCommited and canBeAdded
+        """
         dname, fname = self.splitPath(name)
         
         if fname == '.':
@@ -1248,6 +1347,105 @@
         @return the received dictionary completed with a combination of
             canBeCommited and canBeAdded or None in order to signal an error
         """
+        if self.__wcng:
+            return self.__vcsAllRegisteredStates_wcng(names, dname, shortcut)
+        else:
+            return self.__vcsAllRegisteredStates_wc(names, dname, shortcut)
+        
+    def __vcsAllRegisteredStates_wcng(self, names, dname, shortcut = True):
+        """
+        Private method used to get the registered states of a number of files in the vcs.
+        
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+        
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+        
+        @param names dictionary with all filenames to be checked as keys
+        @param dname directory to check in (string)
+        @param shortcut flag indicating a shortcut should be taken (boolean)
+        @return the received dictionary completed with a combination of 
+            canBeCommited and canBeAdded or None in order to signal an error
+        """
+        if dname.endswith(os.sep):
+            dname = dname[:-1]
+        dname = os.path.normcase(dname)
+        
+        found = False
+        for name in self.statusCache.keys():
+            if name in names:
+                found = True
+                names[name] = self.statusCache[name]
+        
+        if not found:
+            # find the root of the repo
+            repodir = dname
+            while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                repodir = os.path.dirname(repodir)
+                if os.path.splitdrive(repodir)[1] == os.sep:
+                    return names
+            
+            from .SvnDialogMixin import SvnDialogMixin
+            mixin = SvnDialogMixin()
+            client = self.getClient()
+            client.callback_get_login = \
+                mixin._clientLoginCallback
+            client.callback_ssl_server_trust_prompt = \
+                mixin._clientSslServerTrustPromptCallback
+            
+            try:
+                locker = QMutexLocker(self.vcsExecutionMutex)
+                allFiles = client.status(dname, recurse = True, get_all = True, 
+                                              ignore = True, update = False)
+                locker.unlock()
+                dirs = [x for x in names.keys() if os.path.isdir(x)]
+                for file in allFiles:
+                    name = os.path.normcase(file.path)
+                    if file.is_versioned:
+                        if name in names:
+                            names[name] = self.canBeCommitted
+                            dn = name
+                            while os.path.splitdrive(dn)[1] != os.sep and \
+                                  dn != repodir:
+                                dn = os.path.dirname(dn)
+                                if dn in self.statusCache and \
+                                   self.statusCache[dn] == self.canBeCommitted:
+                                    break
+                                self.statusCache[dn] = self.canBeCommitted
+                        self.statusCache[name] = self.canBeCommitted
+                        if dirs:
+                            for d in dirs:
+                                if name.startswith(d):
+                                    names[d] = self.canBeCommitted
+                                    self.statusCache[d] = self.canBeCommitted
+                                    dirs.remove(d)
+                                    break
+                    else:
+                        self.statusCache[name] = self.canBeAdded
+            except pysvn.ClientError:
+                locker.unlock()    # ignore pysvn errors
+        
+        return names
+        
+    def __vcsAllRegisteredStates_wc(self, names, dname, shortcut = True):
+        """
+        Private method used to get the registered states of a number of files in the vcs.
+        
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+        
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+        
+        @param names dictionary with all filenames to be checked as keys
+        @param dname directory to check in (string)
+        @param shortcut flag indicating a shortcut should be taken (boolean)
+        @return the received dictionary completed with a combination of 
+            canBeCommited and canBeAdded or None in order to signal an error
+        """
         if not os.path.isdir(os.path.join(dname, self.adminDir)):
             # not under version control -> do nothing
             return names
@@ -2028,6 +2226,9 @@
         """
         helper = self.__plugin.getProjectHelper()
         helper.setObjects(self, project)
+        self.__wcng = \
+            os.path.exists(os.path.join(project.getProjectPath(), ".svn", "format")) or \
+            os.path.exists(os.path.join(project.getProjectPath(), "_svn", "format"))
         return helper
 
     ############################################################################
--- a/Plugins/VcsPlugins/vcsSubversion/subversion.py	Sat Jan 21 17:27:30 2012 +0100
+++ b/Plugins/VcsPlugins/vcsSubversion/subversion.py	Sun Jan 22 19:27:40 2012 +0100
@@ -127,6 +127,8 @@
         self.__commitData = {}
         self.__commitDialog = None
         
+        self.__wcng = True      # assume new generation working copy metadata format
+        
     def getPlugin(self):
         """
         Public method to get a reference to the plugin object.
@@ -570,22 +572,49 @@
                 dname, fname = self.splitPath(name)
         tree = []
         wdir = dname
-        while not os.path.exists(os.path.join(dname, self.adminDir)):
-            # add directories recursively, if they aren't in the repository already
-            tree.insert(-1, dname)
-            dname = os.path.split(dname)[0]
-            wdir = dname
+        if self.__wcng:
+            repodir = dname
+            while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                repodir = os.path.dirname(repodir)
+                if os.path.splitdrive(repodir)[1] == os.sep:
+                    return  # oops, project is not version controlled
+            while os.path.normcase(dname) != os.path.normcase(repodir) and \
+                  (os.path.normcase(dname) not in self.statusCache or \
+                   self.statusCache[os.path.normcase(dname)] == self.canBeAdded):
+                # add directories recursively, if they aren't in the repository already
+                tree.insert(-1, dname)
+                dname = os.path.dirname(dname)
+                wdir = dname
+        else:
+            while not os.path.exists(os.path.join(dname, self.adminDir)):
+                # add directories recursively, if they aren't in the repository already
+                tree.insert(-1, dname)
+                dname = os.path.dirname(dname)
+                wdir = dname
         self.addArguments(args, tree)
         
         if isinstance(name, list):
             tree2 = []
             for n in name:
-                d = os.path.split(n)[0]
-                while not os.path.exists(os.path.join(d, self.adminDir)):
-                    if d in tree2 + tree:
-                        break
-                    tree2.append(d)
-                    d = os.path.split(d)[0]
+                d = os.path.dirname(n)
+                if self.__wcng:
+                    repodir = d
+                    while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                        repodir = os.path.dirname(repodir)
+                        if os.path.splitdrive(repodir)[1] == os.sep:
+                            return  # oops, project is not version controlled
+                    while os.path.normcase(d) != os.path.normcase(repodir) and \
+                          (d not in tree2 + tree) and \
+                          (os.path.normcase(d) not in self.statusCache or \
+                           self.statusCache[os.path.normcase(d)] == self.canBeAdded):
+                        tree2.append(d)
+                        d = os.path.dirname(d)
+                else:
+                    while not os.path.exists(os.path.join(d, self.adminDir)):
+                        if d in tree2 + tree:
+                            break
+                        tree2.append(d)
+                        d = os.path.dirname(d)
             tree2.reverse()
             self.addArguments(args, tree2)
             self.addArguments(args, name)
@@ -626,22 +655,48 @@
         if isinstance(path, list):
             dname, fnames = self.splitPathList(path)
             for n in path:
-                d = os.path.split(n)[0]
-                while not os.path.exists(os.path.join(d, self.adminDir)):
-                    # add directories recursively,
-                    # if they aren't in the repository already
-                    if d in tree:
-                        break
-                    tree.append(d)
-                    d = os.path.split(d)[0]
+                d = os.path.dirname(n)
+                if self.__wcng:
+                    repodir = d
+                    while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                        repodir = os.path.dirname(repodir)
+                        if os.path.splitdrive(repodir)[1] == os.sep:
+                            return  # oops, project is not version controlled
+                    while os.path.normcase(d) != os.path.normcase(repodir) and \
+                          (d not in tree) and \
+                          (os.path.normcase(d) not in self.statusCache or \
+                           self.statusCache[os.path.normcase(d)] == self.canBeAdded):
+                        tree.append(d)
+                        d = os.path.dirname(d)
+                else:
+                    while not os.path.exists(os.path.join(d, self.adminDir)):
+                        # add directories recursively, 
+                        # if they aren't in the repository already
+                        if d in tree:
+                            break
+                        tree.append(d)
+                        d = os.path.dirname(d)
             tree.reverse()
         else:
             dname, fname = os.path.split(path)
-            while not os.path.exists(os.path.join(dname, self.adminDir)):
-                # add directories recursively,
-                # if they aren't in the repository already
-                tree.insert(-1, dname)
-                dname = os.path.split(dname)[0]
+            if self.__wcng:
+                repodir = dname
+                while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                    repodir = os.path.dirname(repodir)
+                    if os.path.splitdrive(repodir)[1] == os.sep:
+                        return  # oops, project is not version controlled
+                while os.path.normcase(dname) != os.path.normcase(repodir) and \
+                      (os.path.normcase(dname) not in self.statusCache or \
+                       self.statusCache[os.path.normcase(dname)] == self.canBeAdded):
+                    # add directories recursively, if they aren't in the repository already
+                    tree.insert(-1, dname)
+                    dname = os.path.dirname(dname)
+            else:
+                while not os.path.exists(os.path.join(dname, self.adminDir)):
+                    # add directories recursively,
+                    # if they aren't in the repository already
+                    tree.insert(-1, dname)
+                    dname = os.path.dirname(dname)
         if tree:
             self.vcsAdd(tree, True)
         
@@ -1050,6 +1105,50 @@
         @param name filename to check (string)
         @return a combination of canBeCommited and canBeAdded
         """
+        if self.__wcng:
+            return self.__vcsRegisteredState_wcng(name)
+        else:
+            return self.__vcsRegisteredState_wc(name)
+        
+    def __vcsRegisteredState_wcng(self, name):
+        """
+        Private method used to get the registered state of a file in the vcs.
+        
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+        
+        @param name filename to check (string)
+        @return a combination of canBeCommited and canBeAdded
+        """
+        if name.endswith(os.sep):
+            name = name[:-1]
+        name = os.path.normcase(name)
+        dname, fname = self.splitPath(name)
+        
+        if fname == '.' and os.path.isdir(os.path.join(dname, self.adminDir)):
+            return self.canBeCommitted
+        
+        if name in self.statusCache:
+            return self.statusCache[name]
+        
+        name = os.path.normcase(name)
+        states = { name : 0 }
+        states = self.vcsAllRegisteredStates(states, dname, False)
+        if states[name] == self.canBeCommitted:
+            return self.canBeCommitted
+        else:
+            return self.canBeAdded
+        
+    def __vcsRegisteredState_wc(self, name):
+        """
+        Private method used to get the registered state of a file in the vcs.
+        
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+        
+        @param name filename to check (string)
+        @return a combination of canBeCommited and canBeAdded
+        """
         dname, fname = self.splitPath(name)
         
         if fname == '.':
@@ -1080,6 +1179,96 @@
         @return the received dictionary completed with a combination of
             canBeCommited and canBeAdded or None in order to signal an error
         """
+        if self.__wcng:
+            return self.__vcsAllRegisteredStates_wcng(names, dname, shortcut)
+        else:
+            return self.__vcsAllRegisteredStates_wc(names, dname, shortcut)
+        
+    def __vcsAllRegisteredStates_wcng(self, names, dname, shortcut = True):
+        """
+        Private method used to get the registered states of a number of files in the vcs.
+        
+        This is the variant for subversion installations using the new working copy
+        meta-data format.
+        
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+        
+        @param names dictionary with all filenames to be checked as keys
+        @param dname directory to check in (string)
+        @param shortcut flag indicating a shortcut should be taken (boolean)
+        @return the received dictionary completed with a combination of 
+            canBeCommited and canBeAdded or None in order to signal an error
+        """
+        if dname.endswith(os.sep):
+            dname = dname[:-1]
+        dname = os.path.normcase(dname)
+        
+        found = False
+        for name in self.statusCache.keys():
+            if name in names:
+                found = True
+                names[name] = self.statusCache[name]
+        
+        if not found:
+            # find the root of the repo
+            repodir = dname
+            while not os.path.isdir(os.path.join(repodir, self.adminDir)):
+                repodir = os.path.dirname(repodir)
+                if os.path.splitdrive(repodir)[1] == os.sep:
+                    return names
+            
+            ioEncoding = str(Preferences.getSystem("IOEncoding"))
+            process = QProcess()
+            args = []
+            args.append('status')
+            args.append('--verbose')
+            args.append('--non-interactive')
+            args.append(dname)
+            process.start('svn', args)
+            procStarted = process.waitForStarted()
+            if procStarted:
+                finished = process.waitForFinished(30000)
+                if finished and process.exitCode() == 0:
+                    output = \
+                        str(process.readAllStandardOutput(), ioEncoding, 'replace')
+                    for line in output.splitlines():
+                        if self.rx_status1.exactMatch(line):
+                            flags = str(self.rx_status1.cap(1))
+                            path = self.rx_status1.cap(5).strip()
+                        elif self.rx_status2.exactMatch(line):
+                            flags = str(self.rx_status2.cap(1))
+                            path = self.rx_status2.cap(2).strip()
+                        else:
+                            continue
+                        name = os.path.normcase(path)
+                        if flags[0] not in "?I":
+                            if name in names:
+                                names[name] = self.canBeCommitted
+                            self.statusCache[name] = self.canBeCommitted
+                        else:
+                            self.statusCache[name] = self.canBeAdded
+        
+        return names
+        
+    def __vcsAllRegisteredStates_wc(self, names, dname, shortcut = True):
+        """
+        Private method used to get the registered states of a number of files in the vcs.
+        
+        This is the variant for subversion installations using the old working copy
+        meta-data format.
+        
+        <b>Note:</b> If a shortcut is to be taken, the code will only check, if the named
+        directory has been scanned already. If so, it is assumed, that the states for
+        all files has been populated by the previous run.
+        
+        @param names dictionary with all filenames to be checked as keys
+        @param dname directory to check in (string)
+        @param shortcut flag indicating a shortcut should be taken (boolean)
+        @return the received dictionary completed with a combination of 
+            canBeCommited and canBeAdded or None in order to signal an error
+        """
         if not os.path.isdir(os.path.join(dname, self.adminDir)):
             # not under version control -> do nothing
             return names
@@ -1818,6 +2007,9 @@
         """
         helper = self.__plugin.getProjectHelper()
         helper.setObjects(self, project)
+        self.__wcng = \
+            os.path.exists(os.path.join(project.getProjectPath(), ".svn", "format")) or \
+            os.path.exists(os.path.join(project.getProjectPath(), "_svn", "format"))
         return helper
 
     ############################################################################
--- a/changelog	Sat Jan 21 17:27:30 2012 +0100
+++ b/changelog	Sun Jan 22 19:27:40 2012 +0100
@@ -54,6 +54,9 @@
      --- added support for importing patches
      --- added support for exporting patches
      --- added configuration option to create backup files when reverting changes
+  -- Subversion
+     --- changed code to make the subversion plug-ins compatible with the new
+         generation working copy meta-data format
 - View Manager
   -- added an action to reset the zoom factor
 - Web Browser

eric ide

mercurial