diff -r 3d8ba641a83d -r f41d8406c219 Plugins/VcsPlugins/vcsSubversion/subversion.py --- 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 ############################################################################