summaryrefslogtreecommitdiffstats
path: root/powerline/lib/vcs/mercurial.py
diff options
context:
space:
mode:
Diffstat (limited to 'powerline/lib/vcs/mercurial.py')
-rw-r--r--powerline/lib/vcs/mercurial.py88
1 files changed, 88 insertions, 0 deletions
diff --git a/powerline/lib/vcs/mercurial.py b/powerline/lib/vcs/mercurial.py
new file mode 100644
index 0000000..09b6e0b
--- /dev/null
+++ b/powerline/lib/vcs/mercurial.py
@@ -0,0 +1,88 @@
+# vim:fileencoding=utf-8:noet
+from __future__ import (unicode_literals, division, absolute_import, print_function)
+
+import os
+
+import hglib
+
+from powerline.lib.vcs import get_branch_name, get_file_status
+from powerline.lib.path import join
+from powerline.lib.encoding import get_preferred_file_contents_encoding
+
+
+def branch_name_from_config_file(directory, config_file):
+ try:
+ with open(config_file, 'rb') as f:
+ raw = f.read()
+ return raw.decode(get_preferred_file_contents_encoding(), 'replace').strip()
+ except Exception:
+ return 'default'
+
+
+class Repository(object):
+ __slots__ = ('directory', 'create_watcher')
+
+ # hg status -> (powerline file status, repo status flag)
+ statuses = {
+ b'M': ('M', 1), b'A': ('A', 1), b'R': ('R', 1), b'!': ('D', 1),
+ b'?': ('U', 2), b'I': ('I', 0), b'C': ('', 0),
+ }
+ repo_statuses_str = (None, 'D ', ' U', 'DU')
+
+ def __init__(self, directory, create_watcher):
+ self.directory = os.path.abspath(directory)
+ self.create_watcher = create_watcher
+
+ def _repo(self, directory):
+ # Cannot create this object once and use always: when repository updates
+ # functions emit invalid results
+ return hglib.open(directory)
+
+ def status(self, path=None):
+ '''Return status of repository or file.
+
+ Without file argument: returns status of the repository:
+
+ :'D?': dirty (tracked modified files: added, removed, deleted, modified),
+ :'?U': untracked-dirty (added, but not tracked files)
+ :None: clean (status is empty)
+
+ With file argument: returns status of this file: `M`odified, `A`dded,
+ `R`emoved, `D`eleted (removed from filesystem, but still tracked),
+ `U`nknown, `I`gnored, (None)Clean.
+ '''
+ if path:
+ return get_file_status(
+ directory=self.directory,
+ dirstate_file=join(self.directory, '.hg', 'dirstate'),
+ file_path=path,
+ ignore_file_name='.hgignore',
+ get_func=self.do_status,
+ create_watcher=self.create_watcher,
+ )
+ return self.do_status(self.directory, path)
+
+ def do_status(self, directory, path):
+ with self._repo(directory) as repo:
+ if path:
+ path = os.path.join(directory, path)
+ statuses = repo.status(include=path, all=True)
+ for status, paths in statuses:
+ if paths:
+ return self.statuses[status][0]
+ return None
+ else:
+ resulting_status = 0
+ for status, paths in repo.status(all=True):
+ if paths:
+ resulting_status |= self.statuses[status][1]
+ return self.repo_statuses_str[resulting_status]
+
+ def branch(self):
+ config_file = join(self.directory, '.hg', 'branch')
+ return get_branch_name(
+ directory=self.directory,
+ config_file=config_file,
+ get_func=branch_name_from_config_file,
+ create_watcher=self.create_watcher,
+ )