Previously, a VcView diff of a cached version controlled directory could easily become out of date. For example, if the file 'AUTHORS' was a version controlled file in a git repository: > echo "asdf" >> AUTHORS > meld ./ # Double click on the AUTHORS file to view its diff. # Remove the "asdf" at the bottom of a file and save it. # Close the AUTHORS tab. # The state of the AUTHORS file will still show up as modified, even # though it is now unmodified.
This change implements the new update_file_state() for git. Similar funcationality could be added to monotone, darcs, bzr, and arch. Signed-off-by: Peter Tyser <[email protected]> --- Changes since v1: - Used docstring comments - s/get_path_state()/_update_tree_state_cache()/ - Updated comments meld/vc/_vc.py | 9 +++++++++ meld/vc/git.py | 38 +++++++++++++++++++++++++++++--------- meld/vcview.py | 1 + 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/meld/vc/_vc.py b/meld/vc/_vc.py index 4cd5560..09d9c6d 100644 --- a/meld/vc/_vc.py +++ b/meld/vc/_vc.py @@ -136,6 +136,15 @@ class Vc(object): def uncache_inventory(self): pass + def update_file_state(self, path): + """ Update the state of a specific file. For example after a file + has been modified and saved, its state may be out of date and require + updating. This can be implemented for Vc plugins that cache file + states, eg 'git' an 'bzr' so that the top-level file status is always + accurate. + """ + pass + def get_patch_files(self, patch): regex = re.compile(self.PATCH_INDEX_RE, re.M) return [f.strip() for f in regex.findall(patch)] diff --git a/meld/vc/git.py b/meld/vc/git.py index 82c6c23..9b8ec94 100644 --- a/meld/vc/git.py +++ b/meld/vc/git.py @@ -77,7 +77,8 @@ class Vc(_vc.CachedVc): else: return '' - def _lookup_tree_cache(self, rootdir): + def _update_tree_state_cache(self, path, tree_state): + """ Update the state of the file(s) at tree_state['path'] """ while 1: try: # Update the index before getting status, otherwise we could @@ -87,17 +88,17 @@ class Vc(_vc.CachedVc): # Get the status of files that are different in the "index" vs # the HEAD of the git repository proc = _vc.popen([self.CMD, "diff-index", "--name-status", \ - "--cached", "HEAD", "./"], cwd=self.location) + "--cached", "HEAD", path], cwd=self.location) entries = proc.read().split("\n")[:-1] # Get the status of files that are different in the "index" vs # the files on disk proc = _vc.popen([self.CMD, "diff-files", "--name-status", \ - "-0", "./"], cwd=self.location) + "-0", path], cwd=self.location) entries += (proc.read().split("\n")[:-1]) proc = _vc.popen([self.CMD, "ls-files", "--others", \ - "--ignored", "--exclude-standard"], cwd=self.location) + "--ignored", "--exclude-standard", path], cwd=self.location) entries += ("I\t%s" % f for f in proc.read().split("\n")[:-1]) # An unmerged file or a file that has been modified, added to @@ -110,15 +111,34 @@ class Vc(_vc.CachedVc): except OSError, e: if e.errno != errno.EAGAIN: raise + + if len(entries) == 0 and os.path.isfile(path): + # If we're just updating a single file there's a chance that it + # was it was previously modified, and now has been edited + # so that it is un-modified. This will result in an empty + # 'entries' list, and tree_state['path'] will still contain stale + # data. When this corner case occurs we force tree_state['path'] + # to STATE_NORMAL. + tree_state[path] = _vc.STATE_NORMAL + else: + # There are 1 or more modified files, parse their state + for entry in entries: + statekey, name = entry.split("\t", 2) + path = os.path.join(self.root, name.strip()) + state = self.state_map.get(statekey.strip(), _vc.STATE_NONE) + tree_state[path] = state + + def _lookup_tree_cache(self, rootdir): + # Get a list of all files in rootdir, as well as their status tree_state = {} - for entry in entries: - statekey, name = entry.split("\t", 2) - path = os.path.join(self.root, name.strip()) - state = self.state_map.get(statekey.strip(), _vc.STATE_NONE) - tree_state[path] = state + self._update_tree_state_cache("./", tree_state) return tree_state + def update_file_state(self, path): + tree_state = self._get_tree_cache(os.path.dirname(path)) + self._update_tree_state_cache(path, tree_state) + def _get_dirsandfiles(self, directory, dirs, files): tree = self._get_tree_cache(directory) diff --git a/meld/vcview.py b/meld/vcview.py index fcb65d4..e2bafb5 100644 --- a/meld/vcview.py +++ b/meld/vcview.py @@ -594,6 +594,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component): it = self.find_iter_by_name(filename) if it: path = self.model.value_path(it, 0) + self.vc.update_file_state(path) files = self.vc.lookup_files([], [(os.path.basename(path), path)])[1] for e in files: if e.path == path: -- 1.7.1.13.gcfb88 _______________________________________________ meld-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/meld-list
