diff options
-rwxr-xr-x | ranger/config/commands.py | 4 | ||||
-rw-r--r-- | ranger/container/directory.py | 9 | ||||
-rw-r--r-- | ranger/container/fsobject.py | 2 | ||||
-rw-r--r-- | ranger/ext/vcs/__init__.py | 3 | ||||
-rw-r--r-- | ranger/ext/vcs/bzr.py | 31 | ||||
-rw-r--r-- | ranger/ext/vcs/git.py | 63 | ||||
-rw-r--r-- | ranger/ext/vcs/hg.py | 32 | ||||
-rw-r--r-- | ranger/ext/vcs/svn.py | 24 | ||||
-rw-r--r-- | ranger/ext/vcs/vcs.py | 120 | ||||
-rw-r--r-- | ranger/gui/widgets/__init__.py | 2 | ||||
-rw-r--r-- | ranger/gui/widgets/browsercolumn.py | 6 | ||||
-rw-r--r-- | ranger/gui/widgets/statusbar.py | 4 |
12 files changed, 147 insertions, 153 deletions
diff --git a/ranger/config/commands.py b/ranger/config/commands.py index 6012ed4e..4197ca7b 100755 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -1361,7 +1361,7 @@ class stage(Command): if self.fm.thisdir.vcs and self.fm.thisdir.vcs.track: filelist = [f.path for f in self.fm.thistab.get_selection()] try: - self.fm.thisdir.vcs.add(filelist) + self.fm.thisdir.vcs.action_add(filelist) except VcsError as error: self.fm.notify('Unable to stage files: {0:s}'.format(str(error))) self.fm.ui.vcsthread.wakeup() @@ -1380,7 +1380,7 @@ class unstage(Command): if self.fm.thisdir.vcs and self.fm.thisdir.vcs.track: filelist = [f.path for f in self.fm.thistab.get_selection()] try: - self.fm.thisdir.vcs.reset(filelist) + self.fm.thisdir.vcs.action_reset(filelist) except VcsError as error: self.fm.notify('Unable to unstage files: {0:s}'.format(str(error))) self.fm.ui.vcsthread.wakeup() diff --git a/ranger/container/directory.py b/ranger/container/directory.py index a31d4ec9..608eda06 100644 --- a/ranger/container/directory.py +++ b/ranger/container/directory.py @@ -307,8 +307,7 @@ class Directory(FileSystemObject, Accumulator, Loadable): disk_usage = 0 if self.vcs and self.vcs.track and not self.vcs.is_root: - self.vcspathstatus = self.vcs.get_status_subpath( - self.path, is_directory=True) + self.vcsstatus = self.vcs.status_subpath(self.path, is_directory=True) for name in filenames: try: @@ -341,9 +340,9 @@ class Directory(FileSystemObject, Accumulator, Loadable): if item.vcs.is_root: self.has_vcschild = True elif item.is_link and os.path.realpath(item.path) == item.vcs.root: - item.vcspathstatus = item.vcs.rootvcs.get_status_root() + item.vcsstatus = item.vcs.rootvcs.status_root() else: - item.vcspathstatus = item.vcs.get_status_subpath( + item.vcsstatus = item.vcs.status_subpath( item.path, is_directory=True) else: item = File(name, preload=stats, path_is_abs=True, @@ -351,7 +350,7 @@ class Directory(FileSystemObject, Accumulator, Loadable): item.load() disk_usage += item.size if self.vcs and self.vcs.track: - item.vcspathstatus = self.vcs.get_status_subpath(item.path) + item.vcsstatus = self.vcs.status_subpath(item.path) files.append(item) self.percent = 100 * len(files) // len(filenames) diff --git a/ranger/container/fsobject.py b/ranger/container/fsobject.py index c2a8004c..caf6974a 100644 --- a/ranger/container/fsobject.py +++ b/ranger/container/fsobject.py @@ -73,7 +73,7 @@ class FileSystemObject(FileManagerAware, SettingsAware): size = 0 - vcspathstatus = None + vcsstatus = None _linemode = DEFAULT_LINEMODE linemode_dict = dict( diff --git a/ranger/ext/vcs/__init__.py b/ranger/ext/vcs/__init__.py index 3e62310c..36bbb369 100644 --- a/ranger/ext/vcs/__init__.py +++ b/ranger/ext/vcs/__init__.py @@ -1,3 +1,6 @@ +# This file is part of ranger, the console file manager. +# License: GNU GPL version 3, see the file "AUTHORS" for details. + """VCS Extension""" from .vcs import Vcs, VcsError, VcsThread diff --git a/ranger/ext/vcs/bzr.py b/ranger/ext/vcs/bzr.py index 358db8ad..a771dbb4 100644 --- a/ranger/ext/vcs/bzr.py +++ b/ranger/ext/vcs/bzr.py @@ -1,20 +1,22 @@ +# This file is part of ranger, the console file manager. +# License: GNU GPL version 3, see the file "AUTHORS" for details. + """GNU Bazaar module""" import os import re from datetime import datetime - from .vcs import Vcs, VcsError class Bzr(Vcs): - """VCS implementiation for Bzr""" + """VCS implementation for GNU Bazaar""" HEAD="last:1" # Generic #--------------------------- - def _bzr(self, path, args, silent=True, catchout=False, bytes=False): - return self._vcs(path, 'bzr', args, silent=silent, catchout=catchout, bytes=bytes) + def _bzr(self, path, args, silent=True, catchout=False, retbytes=False): + return self._vcs(path, 'bzr', args, silent=silent, catchout=catchout, retbytes=retbytes) def _has_head(self): """Checks whether repo has head""" @@ -67,23 +69,19 @@ class Bzr(Vcs): # Action Interface #--------------------------- - def add(self, filelist=None): - """Adds files to the index, preparing for commit""" + def action_add(self, filelist=None): if filelist != None: self._bzr(self.path, ['add'] + filelist) else: self._bzr(self.path, ['add']) - def reset(self, filelist=None): - """Removes files from the index""" + def action_reset(self, filelist=None): if filelist != None: self._bzr(self.path, ['remove', '--keep', '--new'] + filelist) else: self._bzr(self.path, ['remove', '--keep', '--new']) # Data Interface #--------------------------- - def get_status_subpaths(self): - """Returns a dict indexed by files not in sync their status as values. - Paths are given relative to the root. Strips trailing '/' from dirs.""" - raw = self._bzr(self.path, ['status', '--short', '--no-classify'], catchout=True, bytes=True) + def data_status_subpaths(self): + raw = self._bzr(self.path, ['status', '--short', '--no-classify'], catchout=True, retbytes=True) L = re.findall('^(..)\s*(.*?)\s*$', raw.decode('utf-8'), re.MULTILINE) ret = {} for st, p in L: @@ -91,8 +89,7 @@ class Bzr(Vcs): ret[os.path.normpath(p.strip())] = sta return ret - def get_status_remote(self): - """Returns the url for the remote repo attached to head""" + def data_status_remote(self): try: remote = self._bzr(self.path, ['config', 'parent_location'], catchout=True) except VcsError: @@ -100,13 +97,11 @@ class Bzr(Vcs): return remote.strip() or None - def get_branch(self): - """Returns the current named branch, if this makes sense for the backend. None otherwise""" + def data_branch(self): branch = self._bzr(self.path, ['nick'], catchout=True) return branch or None - def get_info(self, rev=None): - """Gets info about the given revision rev""" + def data_info(self, rev=None): if rev == None: rev = self.HEAD rev = self._sanitize_rev(rev) if rev == self.HEAD and not self._has_head(): return [] diff --git a/ranger/ext/vcs/git.py b/ranger/ext/vcs/git.py index ab7f516f..0de8f770 100644 --- a/ranger/ext/vcs/git.py +++ b/ranger/ext/vcs/git.py @@ -1,10 +1,12 @@ +# This file is part of ranger, the console file manager. +# License: GNU GPL version 3, see the file "AUTHORS" for details. + """Git module""" import os import re from datetime import datetime import json - from .vcs import Vcs, VcsError class Git(Vcs): @@ -25,17 +27,17 @@ class Git(Vcs): # Generic #--------------------------- - def _git(self, args, path=None, silent=True, catchout=False, bytes=False): - """Call git""" + def _git(self, args, path=None, silent=True, catchout=False, retbytes=False): + """Run a git command""" return self._vcs(path or self.path, 'git', args, silent=silent, - catchout=catchout, bytes=bytes) + catchout=catchout, retbytes=retbytes) def _head_ref(self): - """Gets HEAD's ref""" + """Returns HEAD reference""" return self._git(['symbolic-ref', self.HEAD], catchout=True, silent=True) or None def _remote_ref(self, ref): - """Gets remote ref associated to given ref""" + """Returns remote reference associated to given ref""" if ref is None: return None return self._git(['for-each-ref', '--format=%(upstream)', ref], @@ -43,13 +45,15 @@ class Git(Vcs): or None def _log(self, refspec=None, maxres=None, filelist=None): - """Gets a list of dicts containing revision info, for the revisions matching refspec""" + """Returns an array of dicts containing revision info for refspec""" args = [ '--no-pager', 'log', '--pretty={' '%x00short%x00:%x00%h%x00,' - '%x00revid%x00: %x00%H%x00,' - '%x00author%x00: %x00%an <%ae>%x00, %x00date%x00: %ct, %x00summary%x00: %x00%s%x00' + '%x00revid%x00:%x00%H%x00,' + '%x00author%x00:%x00%an <%ae>%x00,' + '%x00date%x00:%ct,' + '%x00summary%x00:%x00%s%x00' '}' ] if refspec: @@ -82,30 +86,21 @@ class Git(Vcs): # Action interface #--------------------------- - def add(self, filelist=None): - """Adds files to the index, preparing for commit""" - if filelist: - self._git(['add', '--all'] + filelist) - else: - self._git(['add', '--all']) + def action_add(self, filelist=[]): + self._git(['add', '--all'] + filelist) - def reset(self, filelist=None): - """Removes files from the index""" - if filelist: - self._git(['reset'] + filelist) - else: - self._git(['reset']) + def action_reset(self, filelist=[]): + self._git(['reset'] + filelist) # Data Interface #--------------------------- - def get_status_root_cheap(self): - """Returns the status of root, very cheap""" + def data_status_root(self): statuses = set() # Paths with status skip = False for line in self._git(['status', '--porcelain', '-z'], - catchout=True, bytes=True).decode('utf-8').split('\x00')[:-1]: + catchout=True, retbytes=True).decode('utf-8').split('\x00')[:-1]: if skip: skip = False continue @@ -113,19 +108,18 @@ class Git(Vcs): if line.startswith('R'): skip = True - for status in self.DIR_STATUS: + for status in self.DIRSTATUSES: if status in statuses: return status return 'sync' - def get_status_subpaths(self): - """Returns a dict (path: status) for paths not in sync. Strips trailing '/' from dirs""" + def data_status_subpaths(self): statuses = {} # Ignored directories for line in self._git( ['ls-files', '-z', '--others', '--directory', '--ignored', '--exclude-standard'], - catchout=True, bytes=True + catchout=True, retbytes=True ).decode('utf-8').split('\x00')[:-1]: if line.endswith('/'): statuses[os.path.normpath(line)] = 'ignored' @@ -133,7 +127,7 @@ class Git(Vcs): # Empty directories for line in self._git( ['ls-files', '-z', '--others', '--directory', '--exclude-standard'], - catchout=True, bytes=True + catchout=True, retbytes=True ).decode('utf-8').split('\x00')[:-1]: if line.endswith('/'): statuses[os.path.normpath(line)] = 'none' @@ -141,7 +135,7 @@ class Git(Vcs): # Paths with status skip = False for line in self._git(['status', '--porcelain', '-z', '--ignored'], - catchout=True, bytes=True).decode('utf-8').split('\x00')[:-1]: + catchout=True, retbytes=True).decode('utf-8').split('\x00')[:-1]: if skip: skip = False continue @@ -151,8 +145,7 @@ class Git(Vcs): return statuses - def get_status_remote(self): - """Checks the status of the repo regarding sync state with remote branch""" + def data_status_remote(self): try: head = self._head_ref() remote = self._remote_ref(head) @@ -170,8 +163,7 @@ class Git(Vcs): else: return 'behind' if behind else 'sync' - def get_branch(self): - """Returns the current named branch, if this makes sense for the backend. None otherwise""" + def data_branch(self): try: head = self._head_ref() except VcsError: @@ -185,8 +177,7 @@ class Git(Vcs): else: return None - def get_info(self, rev=None): - """Gets info about the given revision rev""" + def data_info(self, rev=None): if rev is None: rev = self.HEAD diff --git a/ranger/ext/vcs/hg.py b/ranger/ext/vcs/hg.py index 58651795..39a81d57 100644 --- a/ranger/ext/vcs/hg.py +++ b/ranger/ext/vcs/hg.py @@ -1,19 +1,22 @@ +# This file is part of ranger, the console file manager. +# License: GNU GPL version 3, see the file "AUTHORS" for details. + """Mercurial module""" import os import re from datetime import datetime - from .vcs import Vcs, VcsError class Hg(Vcs): + """VCS implementation for Mercurial""" HEAD = 'tip' # Generic #--------------------------- - def _hg(self, path, args, silent=True, catchout=False, bytes=False): - return self._vcs(path, 'hg', args, silent=silent, catchout=catchout, bytes=bytes) + def _hg(self, path, args, silent=True, catchout=False, retbytes=False): + return self._vcs(path, 'hg', args, silent=silent, catchout=catchout, retbytes=retbytes) def _has_head(self): """Checks whether repo has head""" @@ -71,23 +74,19 @@ class Hg(Vcs): # Action Interface #--------------------------- - def add(self, filelist=None): - """Adds files to the index, preparing for commit""" + def action_add(self, filelist=None): if filelist != None: self._hg(self.path, ['addremove'] + filelist) else: self._hg(self.path, ['addremove']) - def reset(self, filelist=None): - """Removes files from the index""" - if filelist == None: filelist = self.get_status_subpaths().keys() + def action_reset(self, filelist=None): + if filelist == None: filelist = self.data_status_subpaths().keys() self._hg(self.path, ['forget'] + filelist) # Data Interface #--------------------------- - def get_status_subpaths(self): - """Returns a dict indexed by files not in sync their status as values. - Paths are given relative to the root. Strips trailing '/' from dirs.""" - raw = self._hg(self.path, ['status'], catchout=True, bytes=True) + def data_status_subpaths(self): + raw = self._hg(self.path, ['status'], catchout=True, retbytes=True) L = re.findall('^(.)\s*(.*?)\s*$', raw.decode('utf-8'), re.MULTILINE) ret = {} for st, p in L: @@ -97,8 +96,7 @@ class Hg(Vcs): ret[os.path.normpath(p.strip())] = sta return ret - def get_status_remote(self): - """Checks the status of the repo regarding sync state with remote branch""" + def data_status_remote(self): if self.get_remote() == None: return "none" @@ -118,13 +116,11 @@ class Hg(Vcs): elif not ahead and behind: return "behind" elif not ahead and not behind: return "sync" - def get_branch(self): - """Returns the current named branch, if this makes sense for the backend. None otherwise""" + def data_branch(self): branch = self._hg(self.path, ['branch'], catchout=True) return branch or None - def get_info(self, rev=None): - """Gets info about the given revision rev""" + def data_info(self, rev=None): if rev == None: rev = self.HEAD rev = self._sanitize_rev(rev) if rev == self.HEAD and not self._has_head(): return None diff --git a/ranger/ext/vcs/svn.py b/ranger/ext/vcs/svn.py index 94617b1c..a8ee66f3 100644 --- a/ranger/ext/vcs/svn.py +++ b/ranger/ext/vcs/svn.py @@ -1,3 +1,6 @@ +# This file is part of ranger, the console file manager. +# License: GNU GPL version 3, see the file "AUTHORS" for details. + """Subversion module""" from __future__ import with_statement @@ -8,13 +11,14 @@ from datetime import datetime from .vcs import Vcs, VcsError class SVN(Vcs): + """VCS implementation for Subversion""" HEAD = 'HEAD' # Generic #--------------------------- - def _svn(self, path, args, silent=True, catchout=False, bytes=False): - return self._vcs(path, 'svn', args, silent=silent, catchout=catchout, bytes=bytes) + def _svn(self, path, args, silent=True, catchout=False, retbytes=False): + return self._vcs(path, 'svn', args, silent=silent, catchout=catchout, retbytes=retbytes) def _has_head(self): """Checks whether repo has head""" @@ -83,23 +87,23 @@ class SVN(Vcs): # Action Interface #--------------------------- - def add(self, filelist=None): + def action_add(self, filelist=None): """Adds files to the index, preparing for commit""" if filelist != None: self._svn(self.path, ['add'] + filelist) else: self._svn(self.path, ['add']) - def reset(self, filelist=None): + def action_reset(self, filelist=None): """Equivalent to svn revert""" - if filelist == None: filelist = self.get_status_subpaths().keys() + if filelist == None: filelist = self.data_status_subpaths().keys() self._svn(self.path, ['revert'] + filelist) # Data Interface #--------------------------- - def get_status_subpaths(self): + def data_status_subpaths(self): """Returns a dict indexed by files not in sync their status as values. Paths are given relative to the root. Strips trailing '/' from dirs.""" - raw = self._svn(self.path, ['status'], catchout=True, bytes=True) + raw = self._svn(self.path, ['status'], catchout=True, retbytes=True) # logging.debug(raw) L = re.findall(r'^(.)\s*(.*?)\s*$', raw.decode('utf-8'), re.MULTILINE) ret = {} @@ -110,19 +114,19 @@ class SVN(Vcs): ret[os.path.normpath(p.strip())] = sta return ret - def get_status_remote(self): + def data_status_remote(self): """Checks the status of the repo regarding sync state with remote branch. I'm not sure this make sense for SVN so we're just going to return 'sync'""" return 'sync' - def get_branch(self): + def data_branch(self): """Returns the current named branch, if this makes sense for the backend. None otherwise""" return None branch = self._svn(self.path, ['branch'], catchout=True) return branch or None - def get_info(self, rev=None): + def data_info(self, rev=None): """Gets info about the given revision rev""" if rev == None: rev = self.HEAD rev = self._sanitize_rev(rev) diff --git a/ranger/ext/vcs/vcs.py b/ranger/ext/vcs/vcs.py index 69bfcf74..5018fbb9 100644 --- a/ranger/ext/vcs/vcs.py +++ b/ranger/ext/vcs/vcs.py @@ -1,3 +1,6 @@ +# This file is part of ranger, the console file manager. +# License: GNU GPL version 3, see the file "AUTHORS" for details. + """VCS module""" import os @@ -5,7 +8,7 @@ import subprocess import threading class VcsError(Exception): - """Vcs exception""" + """VCS exception""" pass class Vcs(object): @@ -13,21 +16,16 @@ class Vcs(object): This class represents a version controlled path, abstracting the usual operations from the different supported backends. - The backends are declared in te variable self.repo_types, and are derived + The backends are declared in REPOTYPES, and are derived classes from Vcs with the following restrictions: - * do NOT implement __init__. Vcs takes care of this. - - * do not create change internal state. All internal state should be - handled in Vcs + * Override ALL interface methods + * Only override interface methods + * Do NOT modify internal state. All internal state is handled by Vcs - Objects from backend classes should never be created directly. Instead - create objects of Vcs class. The initialization calls update, which takes - care of detecting the right Vcs backend to use and dynamically changes the - object type accordingly. """ - # These are abstracted revs, representing the current index (staged files), + # These are abstracted revisions, representing the current index (staged files), # the current head and nothing. Every backend should redefine them if the # version control has a similar concept, or implement _sanitize_rev method to # clean the rev before using them @@ -35,6 +33,7 @@ class Vcs(object): HEAD = 'HEAD' NONE = 'NONE' + # Backends REPOTYPES = { 'git': {'class': 'Git', 'setting': 'vcs_backend_git'}, 'hg': {'class': 'Hg', 'setting': 'vcs_backend_hg'}, @@ -44,7 +43,7 @@ class Vcs(object): # Possible directory statuses in order of importance with statuses that # don't make sense disabled - DIR_STATUS = ( + DIRSTATUSES = ( 'conflict', 'untracked', 'deleted', @@ -77,15 +76,15 @@ class Vcs(object): self.status_subpaths = {} if not os.access(self.repodir, os.R_OK): - directoryobject.vcspathstatus = 'unknown' + directoryobject.vcsstatus = 'unknown' self.remotestatus = 'unknown' return try: - self.head = self.get_info(self.HEAD) - self.branch = self.get_branch() - self.remotestatus = self.get_status_remote() - self.obj.vcspathstatus = self.get_status_root_cheap() + self.head = self.data_info(self.HEAD) + self.branch = self.data_branch() + self.remotestatus = self.data_status_remote() + self.obj.vcsstatus = self.data_status_root() except VcsError: return @@ -105,14 +104,14 @@ class Vcs(object): # Generic #--------------------------- - def _vcs(self, path, cmd, args, silent=False, catchout=False, bytes=False): - """Executes a VCS command""" + def _vcs(self, path, cmd, args, silent=False, catchout=False, retbytes=False): + """Run a VCS command""" with open(os.devnull, 'w') as devnull: out = devnull if silent else None try: if catchout: output = subprocess.check_output([cmd] + args, stderr=out, cwd=path) - return output if bytes else output.decode('utf-8').strip() + return output if retbytes else output.decode('UTF-8').strip() else: subprocess.check_call([cmd] + args, stderr=out, stdout=out, cwd=path) except subprocess.CalledProcessError: @@ -122,7 +121,7 @@ class Vcs(object): raise VcsError("{0:s} error on {1:s}: File not found".format(cmd, path)) def _get_repotype(self, path): - """Returns the right repo type for path. None if no repo present in path""" + """Get type for path""" for repotype in self.repotypes_settings: repodir = os.path.join(path, '.{0:s}'.format(repotype)) if os.path.exists(repodir): @@ -130,7 +129,7 @@ class Vcs(object): return (None, None) def _find_root(self, path): - """Finds the repository root path. Otherwise returns none""" + """Finds root path""" links = set() while True: if os.path.islink(path): @@ -138,12 +137,16 @@ class Vcs(object): relpath = os.path.relpath(self.path, path) path = os.path.realpath(path) self.path = os.path.normpath(os.path.join(path, relpath)) + repodir, repotype = self._get_repotype(path) if repodir: return (path, repodir, repotype, links) - if path == '/': - break + + path_old = path path = os.path.dirname(path) + if path == path_old: + break + return (None, None, None, None) def _update_walk(self, path, purge): @@ -159,10 +162,10 @@ class Vcs(object): for fileobj in wroot_obj.files_all: if purge: if fileobj.is_directory: - fileobj.vcspathstatus = None + fileobj.vcsstatus = None fileobj.vcs.__init__(fileobj) else: - fileobj.vcspathstatus = None + fileobj.vcsstatus = None continue if fileobj.is_directory: @@ -170,10 +173,10 @@ class Vcs(object): if not fileobj.vcs.track: continue if not fileobj.vcs.is_root: - fileobj.vcspathstatus = wroot_obj.vcs.get_status_subpath( + fileobj.vcsstatus = wroot_obj.vcs.status_subpath( fileobj.path, is_directory=True) else: - fileobj.vcspathstatus = wroot_obj.vcs.get_status_subpath(fileobj.path) + fileobj.vcsstatus = wroot_obj.vcs.status_subpath(fileobj.path) # Remove dead directories for wdir in list(wdirs): @@ -186,7 +189,7 @@ class Vcs(object): wdirs.remove(wdir) def update_tree(self, purge=False): - """Update tree""" + """Update tree state""" self._update_walk(self.root, purge) for path in list(self.rootvcs.links): self._update_walk(path, purge) @@ -195,31 +198,30 @@ class Vcs(object): except KeyError: continue if purge: - dirobj.vcspathstatus = None + dirobj.vcsstatus = None dirobj.vcs.__init__(dirobj.vcs.obj) elif dirobj.vcs.path == self.root: - dirobj.vcspathstatus = self.rootvcs.get_status_root() + dirobj.vcsstatus = self.rootvcs.status_root() else: - dirobj.vcspathstatus = dirobj.vcs.get_status_subpath( - dirobj.path, is_directory=True) + dirobj.vcsstatus = dirobj.vcs.status_subpath(dirobj.path, is_directory=True) if purge: self.rootvcs.__init__(self.rootvcs.obj) def update_root(self): - """Update repository""" + """Update root state""" try: - self.rootvcs.head = self.rootvcs.get_info(self.HEAD) - self.rootvcs.branch = self.rootvcs.get_branch() - self.rootvcs.status_subpaths = self.rootvcs.get_status_subpaths() - self.rootvcs.remotestatus = self.rootvcs.get_status_remote() - self.rootvcs.obj.vcspathstatus = self.rootvcs.get_status_root() + self.rootvcs.head = self.rootvcs.data_info(self.HEAD) + self.rootvcs.branch = self.rootvcs.data_branch() + self.rootvcs.status_subpaths = self.rootvcs.data_status_subpaths() + self.rootvcs.remotestatus = self.rootvcs.data_status_remote() + self.rootvcs.obj.vcsstatus = self.rootvcs.status_root() except VcsError: self.update_tree(purge=True) return False return True def check(self): - """Check repository health""" + """Check health""" if not self.in_repodir \ and (not self.track or (not self.is_root and self._get_repotype(self.path)[0])): self.__init__(self.obj) @@ -228,15 +230,15 @@ class Vcs(object): return False return True - def get_status_root(self): - """Returns the status of root""" + def status_root(self): + """Returns root status""" statuses = set(status for path, status in self.status_subpaths.items()) - for status in self.DIR_STATUS: + for status in self.DIRSTATUSES: if status in statuses: return status return 'sync' - def get_status_subpath(self, path, is_directory=False): + def status_subpath(self, path, is_directory=False): """ Returns the status of path @@ -261,7 +263,7 @@ class Vcs(object): if is_directory: statuses = set(status for subpath, status in self.rootvcs.status_subpaths.items() if subpath.startswith(relpath + '/')) - for status in self.DIR_STATUS: + for status in self.DIRSTATUSES: if status in statuses: return status return 'sync' @@ -269,36 +271,39 @@ class Vcs(object): # Action interface #--------------------------- - def add(self, filelist): - """Adds files to the index, preparing for commit""" + def action_add(self, filelist): + """Adds files to the index""" raise NotImplementedError - def reset(self, filelist): + def action_reset(self, filelist): """Removes files from the index""" raise NotImplementedError # Data interface #--------------------------- - def get_status_root_cheap(self): - """Returns the status of self.root cheaply""" + def data_status_root(self): + """Returns status of self.root cheaply""" raise NotImplementedError - def get_status_subpaths(self): + def data_status_subpaths(self): """Returns a dict indexed by subpaths not in sync with their status as values. - Paths are given relative to self.root. Strips trailing '/' from dirs.""" + Paths are given relative to self.root""" raise NotImplementedError - def get_status_remote(self): - """Checks the status of the entire repo""" + def data_status_remote(self): + """ + Returns remote status of repository + One of ('sync', 'ahead', 'behind', 'diverged', 'none') + """ raise NotImplementedError - def get_branch(self): + def data_branch(self): """Returns the current named branch, if this makes sense for the backend. None otherwise""" raise NotImplementedError - def get_info(self, rev=None): - """Gets info about the given revision rev""" + def data_info(self, rev=None): + """Returns info string about revision rev. None in special cases""" raise NotImplementedError class VcsThread(threading.Thread): @@ -361,6 +366,7 @@ class VcsThread(threading.Thread): """Wakeup thread""" self.wake.set() +# Backend imports import ranger.ext.vcs.git import ranger.ext.vcs.hg import ranger.ext.vcs.bzr diff --git a/ranger/gui/widgets/__init__.py b/ranger/gui/widgets/__init__.py index 200ae8a8..ac1188ca 100644 --- a/ranger/gui/widgets/__init__.py +++ b/ranger/gui/widgets/__init__.py @@ -5,7 +5,7 @@ from ranger.gui.displayable import Displayable class Widget(Displayable): """A class for classification of widgets.""" - vcspathstatus_symb = {'conflict': ('X', ["vcsconflict"]), + vcsstatus_symb = {'conflict': ('X', ["vcsconflict"]), 'untracked': ('+', ["vcschanged"]), 'deleted': ('-', ["vcschanged"]), 'changed': ('*', ["vcschanged"]), diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index 13c8f510..58d07072 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -257,7 +257,7 @@ class BrowserColumn(Pager): metakey = hash(repr(sorted(metadata.items()))) if metadata else 0 key = (self.wid, selected_i == i, drawn.marked, self.main_column, drawn.path in copied, tagged_marker, drawn.infostring, - drawn.vcspathstatus, + drawn.vcsstatus, drawn.vcs.remotestatus \ if drawn.is_directory and drawn.vcs \ and drawn.vcs.is_root and drawn.vcs.track \ @@ -384,8 +384,8 @@ class BrowserColumn(Pager): vcsstring_display.append([vcsstr, ['vcsremote'] + vcscol]) elif self.target.has_vcschild: vcsstring_display.insert(-1, [" ", []]) - if drawn.vcspathstatus: - vcsstr, vcscol = self.vcspathstatus_symb[drawn.vcspathstatus] + if drawn.vcsstatus: + vcsstr, vcscol = self.vcsstatus_symb[drawn.vcsstatus] vcsstring_display.append([vcsstr, ['vcsfile'] + vcscol]) else: vcsstring_display.append([" ", []]) diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py index 9783a7ad..978171e5 100644 --- a/ranger/gui/widgets/statusbar.py +++ b/ranger/gui/widgets/statusbar.py @@ -195,8 +195,8 @@ class StatusBar(Widget): if directory.vcs.rootvcs.remotestatus: vcsstr, vcscol = self.vcsremotestatus_symb[directory.vcs.rootvcs.remotestatus] left.add(vcsstr.strip(), 'vcsremote', *vcscol) - if target.vcspathstatus: - vcsstr, vcscol = self.vcspathstatus_symb[target.vcspathstatus] + if target.vcsstatus: + vcsstr, vcscol = self.vcsstatus_symb[target.vcsstatus] left.add(vcsstr.strip(), 'vcsfile', *vcscol) if directory.vcs.rootvcs.head: left.add_space() |