don't hard-code the path to the python interpreter
[mass-build.git] / vcs.py
diff --git a/vcs.py b/vcs.py
index 89a4920ba006b36753bc7b3ddb8db033b5930da0..3fcca6d6d1975decf40baaf7f8e2fac57fa0d8a5 100644 (file)
--- a/vcs.py
+++ b/vcs.py
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
-import os, git, subprocess, re
+import os, subprocess, re
 
 '''A VCS must have an "update" method with an optional "mode" parameter taking one of the three values below,
 
 '''A VCS must have an "update" method with an optional "mode" parameter taking one of the three values below,
-   a "version" method returning a version name (or None),
-   and a "newVersions" method which checks for new versions and prints the result to standard output.'''
+a "version" method returning a version name (or None),
+and a "newVersions" method which checks for new versions and prints the result to standard output.'''
 MODE_FETCH = 0
 MODE_REBASE = 1
 MODE_RESET = 2
 
 def natural_sort_key(val):
 MODE_FETCH = 0
 MODE_REBASE = 1
 MODE_RESET = 2
 
 def natural_sort_key(val):
-       return [ (int(c) if c.isdigit() else c) for c in re.split('([0-9]+)', val) ]
+    return [ (int(c) if c.isdigit() else c) for c in re.split('([0-9]+)', val) ]
 
 def get_non_digit_prefix(val):
 
 def get_non_digit_prefix(val):
-       return re.match('[^0-9]*', val).group(0)
+    return re.match('[^0-9]*', val).group(0)
+
+class GitCommand:
+    def __getattr__(self, name):
+        def call(*args, get_stderr = False):
+            cmd = ["git", name.replace('_', '-')] + list(args)
+            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT if get_stderr else None)
+            return output.decode('utf-8').strip('\n')
+        return call
+git = GitCommand()
 
 # Fetch updates from git
 class Git:
 
 # Fetch updates from git
 class Git:
-       def __init__(self, folder, config):
-               self.folder = os.path.abspath(folder)
-               self.url = config['url']
-               self.commit = config['version']
-
-       class _ProgressPrinter(git.remote.RemoteProgress):
-               def update(self, op_code, cur_count, max_count=None, message=''):
-                       print self._cur_line+(" "*30)+"\r",
+    def __init__(self, folder, config):
+        self.folder = os.path.abspath(folder)
+        self.url = config['url']
+        self.commit = config['version']
 
 
-       def update(self, mode = MODE_REBASE):
-               isBranch = (self.commit.startswith('origin/'))
-               if isBranch:
-                       branchname = self.commit[len('origin/'):]
-               else:
-                       branchname = "tag"
-               # get us a git repository, and the "origin" remote
-               if os.path.exists(self.folder):
-                       # load existing repo
-                       repo = git.Repo(self.folder)
-                       origin = repo.remotes.origin
-                       origin.config_writer.set_value("url", self.url) # make sure we use the current URL
-               else:
-                       # create a new one
-                       os.makedirs(self.folder)
-                       repo = git.Repo.init(self.folder)
-                       origin = repo.create_remote('origin', self.url)
-               origin.fetch(progress=Git._ProgressPrinter()) # download new data
-               print " "*80+"\r", # clean the line we are in
-               if mode == MODE_FETCH:
-                       return
-               # create/find correct branch
-               if branchname in repo.heads:
-                       branch = repo.heads[branchname]
-               else:
-                       branch = repo.create_head(branchname, self.commit)
-                       if isBranch: # track remote branch
-                               branch.set_tracking_branch(origin.refs[branchname])
-               # update it to the latest remote commit
-               branch.checkout()
-               if mode == MODE_RESET:
-                       repo.head.reset(self.commit, working_tree=True)
-               else:
-                       repo.git.rebase(self.commit)
-               # update submodules
-               repo.git.submodule("update", "--init", "--recursive", "--rebase")
-               # done
-               print "...done",
-               if repo.head.reference.commit != repo.commit(self.commit):
-                       print "(keeping local patches around)",
-               print
+    def update(self, mode = MODE_REBASE):
+        isBranch = (self.commit.startswith('origin/'))
+        if isBranch:
+            branchname = self.commit[len('origin/'):]
+        else:
+            branchname = "tag"
+        # get us a git repository, and the "origin" remote
+        if os.path.exists(self.folder):
+            # load existing repo
+            os.chdir(self.folder)
+            git.remote("set-url", "origin", self.url) # make sure we use the current URL
+        else:
+            # create a new one
+            os.makedirs(self.folder)
+            os.chdir(self.folder)
+            git.init()
+            git.remote("add", "origin", self.url)
+        git.fetch("origin")
+        if mode == MODE_FETCH:
+            return
+        # create/find correct branch
+        if not git.branch("--list", branchname): # the branch does not yet exit
+            git.branch(branchname, self.commit)
+            if isBranch: # make sure we track the correct remote branch
+                git.branch("-u", self.commit, branchname)
+        # update it to the latest remote commit
+        git.checkout(branchname, get_stderr=True)
+        if mode == MODE_RESET:
+            git.reset("--hard", self.commit)
+        else:
+            git.rebase(self.commit)
+        # update submodules
+        git.submodule("update", "--init", "--recursive", "--rebase")
+        # done
+        print("...done", end=' ')
+        if git.rev_parse("HEAD") != git.rev_parse(self.commit):
+            print("(keeping local patches around)", end=' ')
+        print()
 
 
-       def version(self):
-               repo = git.Repo(self.folder)
-               v = repo.git.describe()
-               return v[len(get_non_digit_prefix(v)):] # remove the non-digit prefix from v (so that it starts with a number)
+    def version(self):
+        os.chdir(self.folder)
+        v = git.describe()
+        return v[len(get_non_digit_prefix(v)):] # remove the non-digit prefix from v (so that it starts with a number)
 
 
-       def checkVersions(self):
-               self.update(mode = MODE_FETCH)
-               repo = git.Repo(self.folder)
-               currentVersion = repo.git.describe()
-               # get sorted list of tag names with the same non-digit prefix and higher version number
-               tags = map(str, repo.tags)
-               tags = filter(lambda t: get_non_digit_prefix(t) == get_non_digit_prefix(currentVersion) and natural_sort_key(t) > natural_sort_key(currentVersion), tags)
-               if not tags: return
-               tags.sort(key = natural_sort_key)
-               print "Versions newer than "+currentVersion+" available:"
-               print tags
+    def checkVersions(self):
+        self.update(mode = MODE_FETCH)
+        currentVersion = git.describe()
+        # get sorted list of tag names with the same non-digit prefix and higher version number
+        tags = git.tag().split('\n')
+        tags = [t for t in tags if get_non_digit_prefix(t) == get_non_digit_prefix(currentVersion) and natural_sort_key(t) > natural_sort_key(currentVersion)]
+        if not tags: return
+        tags.sort(key = natural_sort_key)
+        print("Versions newer than "+currentVersion+" available:")
+        print(tags)
 
 # Fetch updates via SVN
 class SVN:
 
 # Fetch updates via SVN
 class SVN:
-       def __init__(self, folder, url):
-               self.folder = os.path.abspath(folder)
-               self.url = url
+    def __init__(self, folder, url):
+        self.folder = os.path.abspath(folder)
+        self.url = url
 
 
-       def update(self, mode = MODE_REBASE):
-               if mode == MODE_FETCH: raise Exception("Just fetching is not supported with SVN")
-               if os.path.exists(self.folder):
-                       os.chdir(self.folder) # go into repository
-                       if mode == MODE_RESET: subprocess.check_call(['svn', 'revert', '-R', '.'])
-                       subprocess.check_call(['svn', 'switch', self.url]) # and update to the URL we got
-               else:
-                       os.makedirs(self.folder) # if even the parent folder does not exist, svn fails
-                       subprocess.check_call(['svn', 'co', self.url, self.folder]) # just download it
-       
-       def version(self):
-               return None
-       
-       def checkVersions(self):
-               print "Version checking not supporting with SVN"
+    def update(self, mode = MODE_REBASE):
+        if mode == MODE_FETCH: raise Exception("Just fetching is not supported with SVN")
+        if os.path.exists(self.folder):
+            os.chdir(self.folder) # go into repository
+            if mode == MODE_RESET: subprocess.check_call(['svn', 'revert', '-R', '.'])
+            subprocess.check_call(['svn', 'switch', self.url]) # and update to the URL we got
+        else:
+            os.makedirs(self.folder) # if even the parent folder does not exist, svn fails
+            subprocess.check_call(['svn', 'co', self.url, self.folder]) # just download it
+    
+    def version(self):
+        return None
+    
+    def checkVersions(self):
+        print("Version checking not supporting with SVN")