123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- """
- Put into Public Domain, by Nicolas Sebrecht.
- Helpers for maintenance scripts.
- """
- from os import chdir, makedirs, system, getcwd
- from os.path import expanduser
- import shlex
- from subprocess import check_output, check_call, CalledProcessError
- import yaml
- FS_ENCODING = 'UTF-8'
- ENCODING = 'UTF-8'
- MAILING_LIST = 'offlineimap-project@lists.alioth.debian.org'
- CACHEDIR = '.git/offlineimap-release'
- EDITOR = 'vim'
- MAILALIASES_FILE = expanduser('~/.mutt/mail_aliases')
- TESTERS_FILE = "{}/testers.yml".format(CACHEDIR)
- ME = "Nicolas Sebrecht <nicolas.s-dev@laposte.net>"
- def run(cmd):
- return check_output(cmd, timeout=5).rstrip()
- def goTo(path):
- try:
- chdir(path)
- return True
- except FileNotFoundError:
- print(("Could not find the '{}' directory in '{}'...".format(
- path, getcwd())
- ))
- return False
- class Author():
- def __init__(self, name, count, email):
- self.name = name
- self.count = count
- self.email = email
- def getName(self):
- return self.name
- def getCount(self):
- return self.count
- def getEmail(self):
- return self.email
- class Git():
- @staticmethod
- def getShortlog(ref):
- shortlog = ""
- cmd = shlex.split("git shortlog --no-merges -n v{}..".format(ref))
- output = run(cmd).decode(ENCODING)
- for line in output.split("\n"):
- if len(line) > 0:
- if line[0] != " ":
- line = " {}\n".format(line)
- else:
- line = " {}\n".format(line.lstrip())
- else:
- line = "\n"
- shortlog += line
- return shortlog
- @staticmethod
- def add(files):
- cmd = shlex.split("git add -- {}".format(files))
- return run(cmd).decode(ENCODING)
- @staticmethod
- def commit(msg):
- cmd = shlex.split("git commit -s -m '{}'".format(msg))
- return run(cmd).decode(ENCODING)
- @staticmethod
- def tag(version):
- cmd = shlex.split("git tag -a 'v{}' -m 'v{}'".format(version, version))
- return run(cmd).decode(ENCODING)
- @staticmethod
- def stash(msg):
- cmd = shlex.split("git stash create '{}'".format(msg))
- return run(cmd).decode(ENCODING)
- @staticmethod
- def mergeFF(ref):
- cmd = shlex.split("git merge --ff '{}'".format(ref))
- return run(cmd).decode(ENCODING)
- @staticmethod
- def getDiffstat(ref):
- cmd = shlex.split("git diff --stat v{}..".format(ref))
- return run(cmd).decode(ENCODING)
- @staticmethod
- def isClean():
- try:
- check_call(shlex.split("git diff --quiet"))
- check_call(shlex.split("git diff --cached --quiet"))
- except CalledProcessError:
- return False
- return True
- @staticmethod
- def buildMessageId():
- cmd = shlex.split(
- "git log HEAD~1.. --oneline --pretty='%H.%t.upcoming.%ce'")
- return run(cmd).decode(ENCODING)
- @staticmethod
- def resetKeep(ref):
- return run(shlex.split("git reset --keep {}".format(ref)))
- @staticmethod
- def getRef(ref):
- return run(shlex.split("git rev-parse {}".format(ref))).rstrip()
- @staticmethod
- def rmTag(tag):
- return run(shlex.split("git tag -d {}".format(tag)))
- @staticmethod
- def checkout(ref, create=False):
- if create:
- create = "-b"
- else:
- create = ""
- cmd = shlex.split("git checkout {} {}".format(create, ref))
- run(cmd)
- head = shlex.split("git rev-parse HEAD")
- revparseRef = shlex.split("git rev-parse {}".format(ref))
- if run(head) != run(revparseRef):
- raise Exception("checkout to '{}' did not work".format(ref))
- @staticmethod
- def makeCacheDir():
- try:
- makedirs(CACHEDIR)
- except FileExistsError:
- pass
- @staticmethod
- def getLocalUser():
- cmd = shlex.split("git config --get user.name")
- name = run(cmd).decode(ENCODING)
- cmd = shlex.split("git config --get user.email")
- email = run(cmd).decode(ENCODING)
- return name, email
- @staticmethod
- def buildDate():
- cmd = shlex.split("git log HEAD~1.. --oneline --pretty='%cD'")
- return run(cmd).decode(ENCODING)
- @staticmethod
- def getAuthorsList(sinceRef):
- authors = []
- cmd = shlex.split("git shortlog --no-merges -sne v{}..".format(sinceRef))
- output = run(cmd).decode(ENCODING)
- for line in output.split("\n"):
- count, full = line.strip().split("\t")
- full = full.split(' ')
- name = ' '.join(full[:-1])
- email = full[-1]
- authors.append(Author(name, count, email))
- return authors
- @staticmethod
- def getCommitsList(sinceRef):
- cmd = shlex.split(
- "git log --no-merges --format='- %h %s. [%aN]' v{}..".format(sinceRef)
- )
- return run(cmd).decode(ENCODING)
- @staticmethod
- def chdirToRepositoryTopLevel():
- cmd = shlex.split("git rev-parse --show-toplevel")
- topLevel = run(cmd)
- chdir(topLevel)
- class OfflineimapInfo():
- def getVersion(self):
- cmd = shlex.split("./offlineimap.py --version")
- return run(cmd).rstrip().decode(FS_ENCODING)
- def editInit(self):
- return system("{} ./offlineimap/__init__.py".format(EDITOR))
- class User():
- """Interact with the user."""
- @staticmethod
- def request(msg, prompt='--> '):
- print(msg)
- return eval(input(prompt))
- @staticmethod
- def pause(msg=False):
- return User.request(msg, prompt="Press Enter to continue..")
- @staticmethod
- def yesNo(msg, defaultToYes=False, prompt='--> '):
- endMsg = " [y/N]: No"
- if defaultToYes:
- endMsg = " [Y/n]: Yes"
- msg += endMsg
- answer = User.request(msg, prompt).lower()
- if answer in ['y', 'yes']:
- return True
- if defaultToYes is not False and answer not in ['n', 'no']:
- return True
- return False
- class Tester():
- def __init__(self, name, email, feedback):
- self.name = name
- self.email = email
- self.feedback = feedback
- def __str__(self):
- return "{} {}".format(self.name, self.email)
- def getName(self):
- return self.name
- def getEmail(self):
- return self.email
- def getFeedback(self):
- return self.feedback
- def positiveFeedback(self):
- return self.feedback is True
- def setFeedback(self, feedback):
- assert feedback in [True, False, None]
- self.feedback = feedback
- def switchFeedback(self):
- self.feedback = not self.feedback
- class Testers():
- def __init__(self):
- self.testers = None
- self._read()
- def _read(self):
- self.testers = []
- with open(TESTERS_FILE, 'r') as fd:
- testers = yaml.load(fd)
- for tester in testers:
- name = tester['name']
- email = tester['email']
- feedback = tester['feedback']
- self.testers.append(Tester(name, email, feedback))
- self.testers.sort(key=lambda x: x.getName().lower())
- @staticmethod
- def listTestersInTeam():
- """Returns a list of emails extracted from my mailaliases file."""
- cmd = shlex.split("grep offlineimap-testers {}".format(MAILALIASES_FILE))
- output = run(cmd).decode(ENCODING)
- emails = output.lstrip("alias offlineimap-testers ").split(', ')
- return emails
- def add(self, name, email, feedback=None):
- self.testers.append(Tester(name, email, feedback))
- def remove(self, tester):
- self.testers.remove(tester)
- def get(self):
- return self.testers
- def getList(self):
- testersList = ""
- for tester in self.testers:
- testersList += "- {}\n".format(tester.getName())
- return testersList
- def getListOk(self):
- testersOk = []
- for tester in self.testers:
- if tester.positiveFeedback():
- testersOk.append(tester)
- return testersOk
- def reset(self):
- for tester in self.testers:
- tester.setFeedback(None)
- def write(self):
- testers = []
- for tester in self.testers:
- testers.append({
- 'name': tester.getName(),
- 'email': tester.getEmail(),
- 'feedback': tester.getFeedback(),
- })
- with open(TESTERS_FILE, 'w') as fd:
- fd.write(yaml.dump(testers))
|