+
+class GitRepository:
+ type = "git"
+
+ def __init__(self, path, options):
+ self.path = path
+ self.options = options
+
+ def name(self):
+ return os.path.basename(self.path)
+
+ def url(self):
+ return self.repo_root()
+
+ def gitweb(self):
+ c = Command("git show | grep commit | awk '{{print $2;}}'", self.options)
+ out = self.__run_in_repo(c.output_of).strip()
+ return "http://git.onelab.eu/?p={}.git;a=commit;h={}".format(self.name(), out)
+
+ def repo_root(self):
+ c = Command("git remote show origin", self.options)
+ out = self.__run_in_repo(c.output_of)
+ for line in out.split('\n'):
+ if line.strip().startswith("Fetch URL:"):
+ return line.split()[2]
+
+ @classmethod
+ def clone(cls, remote, local, options, depth=None):
+ Command("rm -rf {}".format(local), options).run_silent()
+ depth_option = "" if depth is None else " --depth {}".format(depth)
+ Command("git clone{} {} {}".format(depth_option, remote, local), options).run_fatal()
+ return GitRepository(local, options)
+
+ @classmethod
+ def remote_exists(cls, remote, options):
+ return Command("git --no-pager ls-remote {} &> /dev/null".format(remote), options).run()==0
+
+ def tag_exists(self, tagname):
+ command = 'git tag -l | grep "^{}$"'.format(tagname)
+ c = Command(command, self.options)
+ out = self.__run_in_repo(c.output_of, with_stderr=True)
+ return len(out) > 0
+
+ def __run_in_repo(self, fun, *args, **kwargs):
+ cwd = os.getcwd()
+ os.chdir(self.path)
+ ret = fun(*args, **kwargs)
+ os.chdir(cwd)
+ return ret
+
+ def __run_command_in_repo(self, command, ignore_errors=False):
+ c = Command(command, self.options)
+ if ignore_errors:
+ return self.__run_in_repo(c.output_of)
+ else:
+ return self.__run_in_repo(c.run_fatal)
+
+ def __is_commit_id(self, id):
+ c = Command("git show {} | grep commit | awk '{{print $2;}}'".format(id), self.options)
+ ret = self.__run_in_repo(c.output_of, with_stderr=False)
+ if ret.strip() == id:
+ return True
+ return False
+
+ def update(self, subdir=None, recursive=None, branch="master"):
+ if branch == "master":
+ self.__run_command_in_repo("git checkout {}".format(branch))
+ else:
+ self.to_branch(branch, remote=True)
+ self.__run_command_in_repo("git fetch origin --tags")
+ self.__run_command_in_repo("git fetch origin")
+ if not self.__is_commit_id(branch):
+ # we don't need to merge anything for commit ids.
+ self.__run_command_in_repo("git merge --ff origin/{}".format(branch))
+
+ def to_branch(self, branch, remote=True):
+ self.revert()
+ if remote:
+ command = "git branch --track {} origin/{}".format(branch, branch)
+ c = Command(command, self.options)
+ self.__run_in_repo(c.output_of, with_stderr=True)
+ return self.__run_command_in_repo("git checkout {}".format(branch))
+
+ def to_tag(self, tag):
+ self.revert()
+ return self.__run_command_in_repo("git checkout {}".format(tag))
+
+ def tag(self, tagname, logfile):
+ self.__run_command_in_repo("git tag {} -F {}".format(tagname, logfile))
+ self.commit(logfile)
+
+ def diff(self, f=""):
+ c = Command("git diff {}".format(f), self.options)
+ return self.__run_in_repo(c.output_of, with_stderr=True)
+
+ def diff_with_tag(self, tagname):
+ c = Command("git diff {}".format(tagname), self.options)
+ return self.__run_in_repo(c.output_of, with_stderr=True)
+
+ def commit(self, logfile, branch="master"):
+ self.__run_command_in_repo("git add .", ignore_errors=True)
+ self.__run_command_in_repo("git add -u", ignore_errors=True)
+ self.__run_command_in_repo("git commit -F {}".format(logfile), ignore_errors=True)
+ if branch == "master" or self.__is_commit_id(branch):
+ self.__run_command_in_repo("git push")
+ else:
+ self.__run_command_in_repo("git push origin {}:{}".format(branch, branch))
+ self.__run_command_in_repo("git push --tags")