Sun, 22 Jan 2012 19:27:40 +0100
Changed code to make the subversion plug-ins compatible with the new generation working copy meta-data format.
--- a/Documentation/Help/source.qhp Sat Jan 21 17:21:19 2012 +0100 +++ b/Documentation/Help/source.qhp Sun Jan 22 19:27:40 2012 +0100 @@ -8283,8 +8283,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:21:19 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:21:19 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:21:19 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:21:19 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:21:19 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:21:19 2012 +0100 +++ b/changelog Sun Jan 22 19:27:40 2012 +0100 @@ -8,6 +8,10 @@ - Editor -- added capability to change the colours of the edit area independant from the colours of the system style +- Version Control System Interfaces + -- Subversion + --- changed code to make the subversion plug-ins compatible with the new + generation working copy meta-data format Version 5.2.0: - bug fixes