def in_git_repo(): try: git.status() except ErrorReturnCode_128: return False else: return True
def update(): """Update all submodules to Github versions""" if _is_dirty(): sys.exit("Repo must be in clean state before updating. Please commit changes.") git.submodule.update(remote=True, rebase=True) if _is_dirty(): print "Updated repositories:" print git.status(porcelain=True).strip() git.add(all=True) git.commit(m="Update submodules to origin") else: sys.exit('Nothing to update.')
def update(): """Update all submodules to Github versions""" if _is_dirty(): sys.exit( "Repo must be in clean state before updating. Please commit changes." ) git.submodule.update(remote=True, rebase=True) if _is_dirty(): print "Updated repositories:" print git.status(porcelain=True).strip() git.add(all=True) git.commit(m="Update submodules to origin") else: sys.exit('Nothing to update.')
def assert_status_performance(): # The test fails if `gl status` takes more than 100 times # the time `git status` took. MAX_TOLERANCE = 100 t = time.time() gl.status() gl_t = time.time() - t t = time.time() git.status() git_t = time.time() - t self.assertTrue(gl_t < git_t * MAX_TOLERANCE, msg='gl_t {0}, git_t {1}'.format(gl_t, git_t))
def assert_status_performance(): # The test fails if `gl status` takes more than 100 times # the time `git status` took. MAX_TOLERANCE = 100 t = time.time() gl.status() gl_t = time.time() - t t = time.time() git.status() git_t = time.time() - t self.assertTrue( gl_t < git_t*MAX_TOLERANCE, msg='gl_t {0}, git_t {1}'.format(gl_t, git_t))
def status(self): if self.git and self.link is None: # git repo, check it exists & isn't dirty if not os.path.exists(self.path): LOG.info("ERROR book {0} from {1} doesn't exist.".format( self.path, self.git)) else: # chdir to the book & run `git status` cwd = os.getcwd() os.chdir(self.path) if self._check_branch(): git_status = git.status() if "nothing to commit, working directory clean" in git_status: LOG.info("# book {0} OK".format(self.path)) else: LOG.info("# book {0}".format(self.path)) LOG.info(git_status) os.chdir(cwd) elif self.link and self.git is None: # check the link points to the correct location if self._check_link(): LOG.info('# book {0} correctly points to {1}'.format(self.path, self.link)) else: link_target = os.readlink(self.path) LOG.error('ERROR: {0} should point to {1}, it points to {2}'.format(self.path, self.link, link_target)) else: LOG.error('Unknown book type: {0}'.format(self.path))
def status(self): """Get status on the repo. :return: :rtype: """ rd = self.repo_dir logger.debug("pkg path %s", rd) if not rd: print( "unable to find pkg '%s'. %s" % (self.name, did_u_mean(self.name)) ) cwd = os.getcwd() os.chdir(self.repo_dir) logger.debug("cwd: %s, getting status %s ", cwd, self.repo_dir) try: p = git.status(_out=self._sh_stdout('blue'), _err=self._sh_stderr('red')) p.wait() except Exception: pass # logger.warn(e) os.chdir(cwd)
def add(self, paths, msg="Intializating"): """ Initializes Directory as repository if not already git repo. and adds uncommited changes automatically """ for path in paths: global git git = git.bake("--git-dir={0}/.git".format(path), "--work-tree={0}".format(path)) if os.path.isdir(path): if not os.path.isdir(path + "/.git"): try: Log.debug(self, "EEGit: git init at {0}".format(path)) git.init(path) except ErrorReturnCode as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to git init at {0}".format(path)) status = git.status("-s") if len(status.splitlines()) > 0: try: Log.debug(self, "EEGit: git commit at {0}".format(path)) git.add("--all") git.commit("-am {0}".format(msg)) except ErrorReturnCode as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to git commit at {0} ".format(path)) else: Log.debug(self, "EEGit: Path {0} not present".format(path))
def test_concurrent_edition_with_conflict(self): self.page.raw = "- item1" Git().commit(self.page, message="original") response1 = self.client.get(self.edit_url) response2 = self.client.get(self.edit_url) data1 = response1.context[0]['form'].initial data1["raw"] = '- item2' data1["message"] = "add item2" data2 = response2.context[0]['form'].initial data2["raw"] = '- item0' data1["message"] = "add item0" r = self.client.post(self.edit_url, data1) self.assertRedirects(r, reverse('waliki_detail', args=(self.page.slug,))) r = self.client.post(self.edit_url, data2) self.assertRedirects(r, self.edit_url) self.assertEqual('', git.status('--porcelain', self.page.path).stdout.decode('utf8')) self.assertIn('Merged with conflict', git.log("--no-color", "--pretty=format:%s", "-n 1", self.page.path).stdout.decode('utf8')) self.assertRegexpMatches(self.page.raw,'<<<<<<< HEAD\n- item2\n=======\n- item0\n>>>>>>> [0-9a-f]{7}\n') # can edit in conflict response = self.client.get(self.edit_url) data1 = response.context[0]['form'].initial data1["raw"] = '- item0\n- item2' data1["message"] = "fixing :)" response = self.client.post(self.edit_url, data1) self.assertRedirects(response, reverse('waliki_detail', args=(self.page.slug,))) self.assertEqual(self.page.raw, '- item0\n- item2')
def commit(self, page, message='', author=None, parent=None, extra_path=None): path = page.path paths_to_commit = [path] if extra_path: paths_to_commit.append(extra_path) kwargs = {} User = get_user_model() if isinstance(author, User) and author.is_authenticated(): kwargs['author'] = u"%s <%s>" % (author.get_full_name() or author.username, author.email) elif isinstance(author, six.string_types): kwargs['author'] = author try: there_were_changes = parent and parent != self.last_version(page) status = git.status('--porcelain', path).stdout.decode('utf8')[:2] if parent and status != "UU": git.stash() git.checkout('--detach', parent) try: git.stash('pop') except: git.checkout('--theirs', path) if status == 'UU': # See http://stackoverflow.com/a/8062976/811740 kwargs['i'] = True git.add(path) git_commit_cmd = git.commit.bake(allow_empty=True, allow_empty_message=True, m=message, **kwargs) git_commit_cmd('--', *paths_to_commit) last = self.last_version(page) if parent and status != "UU": git.checkout('master') git.merge(last) except ErrorReturnCode as e: # TODO: make this more robust! error = e.stdout.decode('utf8') if 'CONFLICT' in error: # For '-i' attribute see http://stackoverflow.com/q/5827944/811740 git_commit_cmd = git.commit.bake(allow_empty=True, allow_empty_message=True, m=_('Merged with conflict'), i=True, **kwargs) git_commit_cmd('--', *paths_to_commit) raise Page.EditionConflict( _('Automatic merge failed. Please, fix the conflict and save the page.' )) else: raise return there_were_changes
def add(self, paths, msg="Intializating"): """ Initializes Directory as repository if not already git repo. and adds uncommited changes automatically """ for path in paths: global git git = git.bake("--git-dir={0}/.git".format(path), "--work-tree={0}".format(path)) if os.path.isdir(path): if not os.path.isdir(path+"/.git"): try: Log.debug(self, "EEGit: git init at {0}" .format(path)) git.init(path) except ErrorReturnCode as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to git init at {0}" .format(path)) status = git.status("-s") if len(status.splitlines()) > 0: try: Log.debug(self, "EEGit: git commit at {0}" .format(path)) git.add("--all") git.commit("-am {0}".format(msg)) except ErrorReturnCode as e: Log.debug(self, "{0}".format(e)) Log.error(self, "Unable to git commit at {0} " .format(path)) else: Log.debug(self, "EEGit: Path {0} not present".format(path))
def add_to_blacklist(self, items_to_blacklist, username, code_permissions): # Check if we're on master if git("rev-parse", "--abbrev-ref", "HEAD").strip() != "master": return (False, "Not currently on master.") # Check that we're up-to-date with origin (GitHub) git.remote.update() if git("rev-parse", "refs/remotes/origin/master").strip() != git("rev-parse", "master").strip(): return (False, "HEAD isn't at tip of origin's master branch") # Check that blacklisted_websites.txt isn't modified locally. That could get ugly fast if "blacklisted_websites.txt" in git.status(): # Also ugly return (False, "blacklisted_websites.txt modified locally. This is probably bad.") # Store current commit hash current_commit = git("rev-parse", "HEAD").strip() # Add items to file with open("blacklisted_websites.txt", "a+") as blacklisted_websites: last_character = blacklisted_websites.read()[-1:] if last_character != "\n": blacklisted_websites.write("\n") blacklisted_websites.write("\n".join(items_to_blacklist) + "\n") # Checkout a new branch (mostly unnecessary, but may help if we create PRs in the future branch = "auto-blacklist-{0}".format(str(time.time())) git.checkout("-b", branch) # Clear HEAD just in case git.reset("HEAD") git.add("blacklisted_websites.txt") git.commit("-m", "Auto blacklist of {0} by {1} --autopull".format(", ".join(items_to_blacklist), username)) if code_permissions: git.checkout("master") git.merge(branch) git.push() else: git.push("origin", branch) git.checkout("master") if GlobalVars.github_username is None or GlobalVars.github_password is None: return (False, "tell someone to set a GH password") payload = {"title": "{0}: Blacklist {1}".format(username, ", ".join(items_to_blacklist)), "body": "{0} requests blacklist of domains: \n\n - {1}".format(username, "\n - ".join(items_to_blacklist)), "head": branch, "base": "master"} response = requests.post("https://api.github.com/repos/Charcoal-SE/SmokeDetector/pulls", auth=HTTPBasicAuth(GlobalVars.github_username, GlobalVars.github_password), data=json.dumps(payload)) print(response.json()) return (True, "You don't have code privileges, but I've [created a pull request for you]({0}).".format(response.json()["html_url"])) git.checkout(current_commit) # Return to old commit to await CI. This will make Smokey think it's in reverted mode if it restarts if not code_permissions: return (False, "Unable to perform action due to lack of code-level permissions. [Branch pushed](https://github.com/Charcoal-SE/SmokeDetector/tree/{0}), PR at your leisure.".format(branch)) return (True, "Blacklisted {0} - the entry will be applied via autopull if CI succeeds.".format(", ".join(items_to_blacklist)))
def mv(self, sender, page, old_path, author, message, commit=True): status = git.status('--porcelain', old_path).stdout.decode('utf8')[1:2] extra_path = '' if status in ('D', 'M'): git.rm(old_path) extra_path = old_path if commit: self.commit(page, author=author, message=message, extra_path=extra_path)
def mv(self, sender, page, old_path, author, message, commit=True): status = git.status("--porcelain", old_path).stdout.decode("utf8")[1:2] extra_path = "" if status in ("D", "M"): git.rm(old_path) extra_path = old_path if commit: self.commit(page, author=author, message=message, extra_path=extra_path)
def pull(url, path, remote=None): here = str(pwd()).strip() try: cd(path) except OSError: print "path does not exist? {}".format(path) cd(here) return try: git.status() except ErrorReturnCode_128: print "{} is not a git repository!".format(path) cd(here) return git.pull(remote or url, 'master') git.checkout('-f') cd(here)
def script_write(script, dirname, uid, backup_dir=None): dirname = Path(dirname) if backup_dir is None: backup_dir = dirname / 'backup' else: backup_dir = Path(backup_dir) if uid: cmd_file = dirname / ('kea2.%s.sh' % uid) else: cmd_file = dirname / 'kea2.sh' if not dirname.exists(): os.makedirs(dirname) try: output = git('rev-parse') ingit = True lg.debug("In a git repository - add & commit the script") except ErrorReturnCode as e: lg.info("not git - backing up the cmd file") ingit = False if cmd_file.exists(): #check if in git: if ingit: for line in git.status('-s', cmd_file): _status, _filename = line.strip().split(None, 1) lg.warning('git status prewrite: %s %s', _status, _filename) if _filename != cmd_file: lg.warning("this is not the file we want: %s", _filename) continue if _status == '??': git.add(cmd_file) if _status in ['??', 'A', 'M']: lg.warning("git commit old version of %s", cmd_file) git.commit( cmd_file, m='autocommit by kea2 - prepare for new version') else: #not in a git repository - copy file to a temp file ocf_stat = cmd_file.stat() timestamp = time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime(ocf_stat.st_ctime)) if not backup_dir.exists(): os.makedirs(backup_dir) new_file_name = backup_dir / ('_kea2.%s.%s.sh' % (uid, timestamp)) lg.info("rename old %s to %s", cmd_file, new_file_name) cmd_file.move(new_file_name) script = script.rstrip() with open(cmd_file, 'w') as F: F.write(script) F.write('\n') cmd_file.chmod('a+x') return cmd_file
def script_write(script, dirname, uid, backup_dir=None): dirname = Path(dirname) if backup_dir is None: backup_dir = dirname / 'backup' else: backup_dir = Path(backup_dir) if uid: cmd_file = dirname / ('kea2.%s.sh' % uid) else: cmd_file = dirname / 'kea2.sh' if not dirname.exists(): os.makedirs(dirname) try: output = git('rev-parse') ingit = True lg.debug("In a git repository - add & commit the script") except ErrorReturnCode as e: lg.info("not git - backing up the cmd file") ingit = False if cmd_file.exists(): #check if in git: if ingit: for line in git.status('-s', cmd_file): _status, _filename = line.strip().split(None, 1) lg.warning('git status prewrite: %s %s', _status, _filename) if _filename != cmd_file: lg.warning("this is not the file we want: %s", _filename) continue if _status == '??': git.add(cmd_file) if _status in ['??', 'A', 'M']: lg.warning("git commit old version of %s", cmd_file) git.commit(cmd_file, m='autocommit by kea2 - prepare for new version') else: #not in a git repository - copy file to a temp file ocf_stat = cmd_file.stat() timestamp = time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime(ocf_stat.st_ctime)) if not backup_dir.exists(): os.makedirs(backup_dir) new_file_name = backup_dir / ('_kea2.%s.%s.sh' % (uid, timestamp)) lg.info("rename old %s to %s", cmd_file, new_file_name) cmd_file.move(new_file_name) script = script.rstrip() with open(cmd_file, 'w') as F: F.write(script) F.write('\n') cmd_file.chmod('a+x') return cmd_file
def prepare(self): modified = re.compile('^[MA]\s+(?P<name>.*)$') self.files = [] mod_files = git.status('--porcelain') for mod_file in mod_files.splitlines(): match = modified.match(mod_file) if match: self.files.append(match.group('name')) print highlight('Stashing all untracked changes...') git.stash('--include-untracked', '--keep-index')
def _git_info(path): from sh import git git = git.bake('--no-pager') rev_parse = getattr(git, 'rev-parse') R = {'branch': rev_parse('--abbrev-ref', 'HEAD', _cwd=path).strip(), 'revision': rev_parse('HEAD', _cwd=path).strip(), 'untracked': getattr(git, 'ls-files')('--others', '--exclude-standard', '--directory', _cwd=path).strip(), 'status': git.status('-s', _cwd=path).strip(), 'diff': git.diff(_cwd=path).strip()} R['clean'] = len(R['diff']) == 0 return R
def git_commit(self, message='maintenance', push=False): sucess = False if (cd and git) is not False: # switch to project folder cd(self.paths['root']) # add changes git.add('.') git.add('-A') # commit changes try: print git.commit("-m '%s'" % message) sucess = True # get status except: print git.status() else: print 'sh and/or git not available.\n' # push to remote server if sucess and push: self.git_push()
def _repo_dirty(self): """Return True if the repository is dirty.""" UNCHANGED_STATUSES = (' ', '?', '!') for status_line in git.status(porcelain=True): if not(status_line[0] in UNCHANGED_STATUSES and status_line[1] in UNCHANGED_STATUSES): return True return False
def _repo_dirty(self): """Return True if the repository is dirty.""" UNCHANGED_STATUSES = (' ', '?', '!') for status_line in git.status(porcelain=True): if not (status_line[0] in UNCHANGED_STATUSES and status_line[1] in UNCHANGED_STATUSES): return True return False
def checkfilestatus(self, repo, filepath): """ Checks status of file, If its tracked or untracked. """ global git git = git.bake("--git-dir={0}/.git".format(repo), "--work-tree={0}".format(repo)) status = git.status("-s", "{0}".format(filepath)) if len(status.splitlines()) > 0: return True else: return False
def test_concurrent_edition_no_existent_page(self): assert not Page.objects.filter(slug='test2').exists() url = reverse('waliki_edit', args=('test2', )) response1 = self.client.post(url) response2 = self.client.post(url) page = Page.objects.get(slug='test2') data1 = response1.context[0]['form'].initial data1["raw"] = '- item2\n' data1["message"] = "add item2" data1["title"] = "a title" data2 = response2.context[0]['form'].initial data2["raw"] = '- item0\n' data2["message"] = "add item0" data2["title"] = "another title" self.client.post(url, data1) with patch('waliki.views.messages') as messages: response = self.client.post(url, data2) # there is a warning self.assertTrue(messages.warning.called) self.assertIsInstance(messages.warning.call_args[0][1], Page.EditionConflict) # redirect self.assertRedirects(response, url) # file committed with conflict self.assertEqual( '', git.status('--porcelain', page.path).stdout.decode('utf8')) self.assertIn( 'Merged with conflict', git.log("--pretty=format:%s", "-n 1", page.path).stdout.decode('utf8')) self.assertRegexpMatches( page.raw, r"""<<<<<<< HEAD\n- item2 =======\n- item0\n>>>>>>> [0-9a-f]{7}\n""") page = Page.objects.get(slug='test2') # refresh self.assertEqual(page.title, "another title") # can edit in conflict response = self.client.get(url) data1 = response.context[0]['form'].initial data1["raw"] = '- item0\n- item2\n' data1["message"] = "fixing :)" response = self.client.post(url, data1) self.assertRedirects(response, reverse('waliki_detail', args=(page.slug, ))) self.assertEqual(page.raw, '- item0\n- item2\n')
def needs_commit(self): import os try: for line in git.status(porcelain=True): if line.strip(): return True return False except ErrorReturnCode_128: logger.error("Needs_commit failed in {}".format(os.getcwd())) return False
def needs_commit(self): import os try: for line in git.status(porcelain=True): if line.strip(): return True return False except ErrorReturnCode_128: global_logger.error("Needs_commit failed in {}".format( os.getcwd())) return False
def test_concurrent_edition_no_existent_page(self): assert not Page.objects.filter(slug="test2").exists() url = reverse("waliki_edit", args=("test2",)) response1 = self.client.post(url) response2 = self.client.post(url) page = Page.objects.get(slug="test2") data1 = response1.context[0]["form"].initial data1["raw"] = "- item2\n" data1["message"] = "add item2" data1["title"] = "a title" data2 = response2.context[0]["form"].initial data2["raw"] = "- item0\n" data2["message"] = "add item0" data2["title"] = "another title" self.client.post(url, data1) with patch("waliki.views.messages") as messages: response = self.client.post(url, data2) # there is a warning self.assertTrue(messages.warning.called) self.assertIsInstance(messages.warning.call_args[0][1], Page.EditionConflict) # redirect self.assertRedirects(response, url) # file committed with conflict self.assertEqual("", git.status("--porcelain", page.path).stdout.decode("utf8")) self.assertIn("Merged with conflict", git.log("--pretty=format:%s", "-n 1", page.path).stdout.decode("utf8")) self.assertRegexpMatches( page.raw, r"""<<<<<<< HEAD\n- item2 =======\n- item0\n>>>>>>> [0-9a-f]{7}\n""", ) page = Page.objects.get(slug="test2") # refresh self.assertEqual(page.title, "another title") # can edit in conflict response = self.client.get(url) data1 = response.context[0]["form"].initial data1["raw"] = "- item0\n- item2\n" data1["message"] = "fixing :)" response = self.client.post(url, data1) self.assertRedirects(response, reverse("waliki_detail", args=(page.slug,))) self.assertEqual(page.raw, "- item0\n- item2\n")
def commit(self, page, message="", author=None, parent=None, extra_path=None): path = page.path paths_to_commit = [path] if extra_path: paths_to_commit.append(extra_path) kwargs = {} if isinstance(author, User) and author.is_authenticated(): kwargs["author"] = u"%s <%s>" % (author.get_full_name() or author.username, author.email) elif isinstance(author, six.string_types): kwargs["author"] = author try: there_were_changes = parent and parent != self.last_version(page) status = git.status("--porcelain", path).stdout.decode("utf8")[:2] if parent and status != "UU": git.stash() git.checkout("--detach", parent) try: git.stash("pop") except: git.checkout("--theirs", path) if status == "UU": # See http://stackoverflow.com/a/8062976/811740 kwargs["i"] = True git.add(path) git_commit_cmd = git.commit.bake(allow_empty=True, allow_empty_message=True, m=message, **kwargs) git_commit_cmd("--", *paths_to_commit) last = self.last_version(page) if parent and status != "UU": git.checkout("master") git.merge(last) except ErrorReturnCode as e: # TODO: make this more robust! error = e.stdout.decode("utf8") if "CONFLICT" in error: # For '-i' attribute see http://stackoverflow.com/q/5827944/811740 git_commit_cmd = git.commit.bake( allow_empty=True, allow_empty_message=True, m=_("Merged with conflict"), i=True, **kwargs ) git_commit_cmd("--", *paths_to_commit) raise Page.EditionConflict(_("Automatic merge failed. Please, fix the conflict and save the page.")) else: raise return there_were_changes
def commit(self, page, message='', author=None, parent=None, extra_path=None): path = page.path paths_to_commit = [path] if extra_path: paths_to_commit.append(extra_path) kwargs = {} User = get_user_model() if isinstance(author, User) and is_authenticated(author): kwargs['author'] = u"%s <%s>" % (author.get_full_name() or author.username, author.email) elif isinstance(author, six.string_types): kwargs['author'] = author try: there_were_changes = parent and parent != self.last_version(page) status = git.status('--porcelain', path).stdout.decode('utf8')[:2] if parent and status != "UU": git.stash() git.checkout('--detach', parent) try: git.stash('pop') except: git.checkout('--theirs', path) if status == 'UU': # See http://stackoverflow.com/a/8062976/811740 kwargs['i'] = True git.add(path) git_commit_cmd = git.commit.bake(allow_empty=True, allow_empty_message=True, m=message, **kwargs) git_commit_cmd('--', *paths_to_commit) last = self.last_version(page) if parent and status != "UU": git.checkout('master') git.merge(last) except ErrorReturnCode as e: # TODO: make this more robust! error = e.stdout.decode('utf8') if 'CONFLICT' in error: # For '-i' attribute see http://stackoverflow.com/q/5827944/811740 git_commit_cmd = git.commit.bake(allow_empty=True, allow_empty_message=True, m=_('Merged with conflict'), i=True, **kwargs) git_commit_cmd('--', *paths_to_commit) raise Page.EditionConflict(_('Automatic merge failed. Please, fix the conflict and save the page.')) else: raise return there_were_changes
def test_concurrent_edition_no_existent_page(self): assert not Page.objects.filter(slug='test2').exists() url = reverse('waliki_edit', args=('test2',)) response1 = self.client.get(url) response2 = self.client.get(url) page = Page.objects.get(slug='test2') data1 = response1.context[0]['form'].initial data1["raw"] = '- item2\n' data1["message"] = "add item2" data1["title"] = "a title" data2 = response2.context[0]['form'].initial data2["raw"] = '- item0\n' data2["message"] = "add item0" data2["title"] = "another title" self.client.post(url, data1) with patch('waliki.views.messages') as messages: response = self.client.post(url, data2) # there is a warning self.assertTrue(messages.warning.called) self.assertIsInstance(messages.warning.call_args[0][1], Page.EditionConflict) # redirect self.assertRedirects(response, url) # file in conflict self.assertEqual('UU', git.status('--porcelain', page.path).stdout.decode('utf8')[:2]) self.assertRegexpMatches(page.raw, r"""<<<<<<< HEAD\n- item2 =======\n- item0\n>>>>>>> [0-9a-f]{7}\n""") page = Page.objects.get(slug='test2') # refresh self.assertEqual(page.title, "another title") # can edit in conflict response = self.client.get(url) data1 = response1.context[0]['form'].initial data1["raw"] = '- item0\n- item2\n' data1["message"] = "fixing :)" response = self.client.post(url, data1) self.assertRedirects(response, reverse('waliki_detail', args=(page.slug,))) self.assertEqual(page.raw, '- item0\n- item2\n')
def switch(target_branch): mark_message = '***mark***' try: res = git.status() except ErrorReturnCode: print(get_stderr(res)) print('失败!该文件夹没有初始化') exit(-1) is_clean = re.match(".*nothing to commit, working tree clean.*", get_stdout(res), re.S) if not is_clean: print('工作区不干净,mark提交...') git.add('--all') git.commit('-a', '-m', mark_message) git.switch(target_branch) code, output = subprocess.getstatusoutput('git log -1 --pretty=format:"%s" ' + target_branch) if code == 0: if output == mark_message: git.reset('HEAD~') else: print("查看commit message出错!") exit(-1) print('切换到%s' % target_branch)
def merge(self, branch, base_branch="master"): """ Merge the the given WIP branch to master (or base_branch, if specified) If the merge fails, the merge will be aborted and then a MergeException will be thrown. The message of the MergeException will be the "git status" output, so details about merge conflicts can be determined. """ os.chdir(self.repo) current_branch = self.current_branch() if current_branch != base_branch: git.checkout(base_branch) # Always create a merge commit, even if we could fast forward, so we know # when merges occured try: merge_output = git.merge("--no-ff", branch) except sh.ErrorReturnCode: # attempt to reset things so other operations can # continue output = git.status() git.merge("--abort") # re-raise the exception so other code can decide # what to do with it raise MergeException(output) # the merge succeeded, so remove the local WIP branch git.branch("-d", branch) new_sha = git("rev-parse","HEAD") return new_sha.strip()
def commit(self, page, message='', author=None, parent=None): path = page.path kwargs = {} if isinstance(author, User) and author.is_authenticated(): kwargs['author'] = u"%s <%s>" % (author.get_full_name() or author.username, author.email) elif isinstance(author, six.string_types): kwargs['author'] = author try: there_were_changes = parent and parent != self.last_version(page) status = git.status('--porcelain', path).stdout.decode('utf8')[:2] if parent and status != "UU": git.stash() git.checkout('--detach', parent) try: git.stash('pop') except: git.checkout('--theirs', path) if status == 'UU': # See http://stackoverflow.com/a/8062976/811740 kwargs['i'] = True git.add(path) git.commit(path, allow_empty_message=True, m=message, **kwargs) last = self.last_version(page) if parent and status != "UU": git.checkout('master') git.merge(last) except ErrorReturnCode as e: # TODO: make this more robust! error = e.stdout.decode('utf8') if 'CONFLICT' in error: raise Page.EditionConflict(_('Automatic merge failed. Please, fix the conflict and save the page.')) else: raise return there_were_changes
def merge(self, branch, base_branch="master"): """ Merge the the given WIP branch to master (or base_branch, if specified) If the merge fails, the merge will be aborted and then a MergeException will be thrown. The message of the MergeException will be the "git status" output, so details about merge conflicts can be determined. """ os.chdir(self.repo) current_branch = self.current_branch() if current_branch != base_branch: git.checkout(base_branch) # Always create a merge commit, even if we could fast forward, so we know # when merges occured try: merge_output = git.merge("--no-ff", branch) except sh.ErrorReturnCode: # attempt to reset things so other operations can # continue output = git.status() git.merge("--abort") # re-raise the exception so other code can decide # what to do with it raise MergeException(output) # the merge succeeded, so remove the local WIP branch git.branch("-d", branch) new_sha = git("rev-parse", "HEAD") return new_sha.strip()
def status(self): """Get status on the repo. :return: :rtype: """ rd = self.repo_dir logger.debug("pkg path %s", rd) if not rd: print("unable to find pkg '%s'. %s" % (self.name, did_u_mean(self.name))) cwd = os.getcwd() os.chdir(self.repo_dir) logger.debug("cwd: %s, getting status %s ", cwd, self.repo_dir) try: p = git.status(_out=self._sh_stdout('blue'), _err=self._sh_stderr('red')) p.wait() except Exception: pass # logger.warn(e) os.chdir(cwd)
def current_git_status(): return git.status()
def add_to_blacklist(self, **kwargs): blacklist = kwargs.get("blacklist", "website") items_to_blacklist = kwargs.get("items_to_blacklist", []) username = kwargs.get("username", "") chat_profile_link = kwargs.get("chat_profile_link", "http://chat.stackexchange.com/users") code_permissions = kwargs.get("code_permissions", False) if blacklist == "website": blacklist_file_name = "blacklisted_websites.txt" elif blacklist == "keyword": blacklist_file_name = "bad_keywords.txt" elif blacklist == "username": blacklist_file_name = "blacklisted_usernames.txt" # Check if we're on master if git("rev-parse", "--abbrev-ref", "HEAD").strip() != "master": return (False, "Not currently on master.") # Check that we're up-to-date with origin (GitHub) git.remote.update() if git("rev-parse", "refs/remotes/origin/master").strip() != git( "rev-parse", "master").strip(): return (False, "HEAD isn't at tip of origin's master branch") # Check that blacklisted_websites.txt isn't modified locally. That could get ugly fast if blacklist_file_name in git.status(): # Also ugly return (False, "{0} modified locally. This is probably bad.".format( blacklist_file_name)) # Store current commit hash current_commit = git("rev-parse", "HEAD").strip() # Add items to file with open(blacklist_file_name, "a+") as blacklist_file: last_character = blacklist_file.read()[-1:] if last_character != "\n": blacklist_file.write("\n") blacklist_file.write("\n".join(items_to_blacklist) + "\n") # Checkout a new branch (for PRs for non-code-privileged people) branch = "auto-blacklist-{0}".format(str(time.time())) git.checkout("-b", branch) # Clear HEAD just in case git.reset("HEAD") git.add(blacklist_file_name) git.commit( "-m", u"Auto blacklist of {0} by {1} --autopull".format( ", ".join(items_to_blacklist), username)) if code_permissions: git.checkout("master") git.merge(branch) git.push() else: git.push("origin", branch) git.checkout("master") if GlobalVars.github_username is None or GlobalVars.github_password is None: return (False, "Tell someone to set a GH password") list_of_domains = "" for domain in range(len(items_to_blacklist)): list_of_domains += "\n - {0} - [MS search](https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93&body_is_regex=1&body={0})".format( items_to_blacklist[domain]) payload = { "title": "{0}: Blacklist {1}".format(username, ", ".join(items_to_blacklist)), "body": "[{0}]({1}) requests the blacklist of the following {2}(s): \n{3}\n<!-- METASMOKE-BLACKLIST {4} -->" .format(username, chat_profile_link, blacklist, list_of_domains, "|".join(items_to_blacklist)), "head": branch, "base": "master" } response = requests.post( "https://api.github.com/repos/Charcoal-SE/SmokeDetector/pulls", auth=HTTPBasicAuth(GlobalVars.github_username, GlobalVars.github_password), data=json.dumps(payload)) print(response.json()) return ( True, "You don't have code privileges, but I've [created a pull request for you]({0})." .format(response.json()["html_url"])) git.checkout( current_commit ) # Return to old commit to await CI. This will make Smokey think it's in reverted mode if it restarts return ( True, "Blacklisted {0} - the entry will be applied via autopull if CI succeeds." .format(", ".join(items_to_blacklist)))
def add_to_blacklist(**kwargs): blacklist = kwargs.get("blacklist", "") item_to_blacklist = kwargs.get("item_to_blacklist", "") username = kwargs.get("username", "") chat_profile_link = kwargs.get("chat_profile_link", "http://chat.stackexchange.com/users") code_permissions = kwargs.get("code_permissions", False) # Make sure git credentials are set up if git.config("--global", "--get", "user.name") == "": return (False, "Tell someone to run `git config --global user.name \"SmokeDetector\"`") if git.config("--global", "--get", "user.name") == "": return (False, "Tell someone to run `git config --global user.email \"[email protected]\"`") if blacklist == "": # If we broke the code, and this isn't assigned, error out before doing anything, but do # so gracefully with a nice error message. return (False, "Programming Error - Critical information missing for GitManager: blacklist") if item_to_blacklist == "": # If we broke the code, and this isn't assigned, error out before doing anything, but do # so gracefully with a nice error message. return (False, "Programming Error - Critical information missing for GitManager: item_to_blacklist") item_to_blacklist = item_to_blacklist.replace("\s", " ") if blacklist == "website": blacklist_file_name = "blacklisted_websites.txt" ms_search_option = "&body_is_regex=1&body=" elif blacklist == "keyword": blacklist_file_name = "bad_keywords.txt" ms_search_option = "&body_is_regex=1&body=" elif blacklist == "username": blacklist_file_name = "blacklisted_usernames.txt" ms_search_option = "&username_is_regex=1&username="******"Invalid blacklist type specified, something has broken badly!") git.checkout("master") try: git.pull() except: pass # Check that we're up-to-date with origin (GitHub) git.remote.update() if git("rev-parse", "refs/remotes/origin/master").strip() != git("rev-parse", "master").strip(): return (False, "HEAD isn't at tip of origin's master branch") # Check that blacklisted_websites.txt isn't modified locally. That could get ugly fast if blacklist_file_name in git.status(): # Also ugly return (False, "{0} is modified locally. This is probably bad.".format(blacklist_file_name)) # Add item to file with open(blacklist_file_name, "a+") as blacklist_file: last_character = blacklist_file.read()[-1:] if last_character != "\n": blacklist_file.write("\n") blacklist_file.write(item_to_blacklist + "\n") # Checkout a new branch (for PRs for non-code-privileged people) branch = "auto-blacklist-{0}".format(str(time.time())) git.checkout("-b", branch) # Clear HEAD just in case git.reset("HEAD") git.add(blacklist_file_name) git.commit("-m", u"Auto blacklist of {0} by {1} --autopull".format(item_to_blacklist, username)) if code_permissions: git.checkout("master") git.merge(branch) git.push() else: git.push("origin", branch) git.checkout("master") if GlobalVars.github_username is None or GlobalVars.github_password is None: return (False, "Tell someone to set a GH password") payload = {"title": u"{0}: Blacklist {1}".format(username, item_to_blacklist), "body": u"[{0}]({1}) requests the blacklist of the {2} {3}. See the Metasmoke search [here]" "(https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93{4}{5})\n" u"<!-- METASMOKE-BLACKLIST-{6} {3} -->".format(username, chat_profile_link, blacklist, item_to_blacklist, ms_search_option, item_to_blacklist.replace(" ", "+"), blacklist.upper()), "head": branch, "base": "master"} response = requests.post("https://api.github.com/repos/Charcoal-SE/SmokeDetector/pulls", auth=HTTPBasicAuth(GlobalVars.github_username, GlobalVars.github_password), data=json.dumps(payload)) print(response.json()) try: git.checkout("deploy") # Return to deploy, pending the accept of the PR in Master. return (True, "You don't have code privileges, but I've [created a pull request for you]({0}).".format( response.json()["html_url"])) except KeyError: # Error capture/checking for any "invalid" GH reply without an 'html_url' item, # which will throw a KeyError. if "bad credentials" in str(response.json()['message']).lower(): # Capture the case when GH credentials are bad or invalid return (False, "Something is wrong with the GH credentials, tell someone to check them.") else: # Capture any other invalid response cases. return (False, "A bad or invalid reply was received from GH, the message was: %s" % response.json()['message']) git.checkout("deploy") # Return to deploy to await CI. return (True, "Blacklisted {0}".format(item_to_blacklist))
def _is_dirty(): return "" != git.status(porcelain=True).strip()
def mv(self, page, old_path, author, message): status = git.status('--porcelain', old_path).stdout.decode('utf8')[1:2] if status == 'D': git.rm(old_path) self.commit(page, author=author, message=message)
def clean(): if path.exists('dist'): rmtree('dist') vers = input('Did you change the version? (y/n) ') if vers != 'y' and vers != 'n': print('Expected "y" or "n", instead found {}. Exiting.'.format(vers)) exit(1) if vers == 'n': exit(0) status = git.status() branch = git.branch() if 'master' not in branch: print('Must be on branch "master". Exiting.') exit(1) if 'Changes not staged for commit' in status or 'Untracked files' in status or 'Changes to be committed' in status: # get user input for if they want to commit all current changes # and continue with the deploy script # exit if no commit = input( 'Changes were detected, would you like to commit all current changes? (y/n) ' ) if commit != 'y' and commit != 'n': print('Expected "y" or "n", instead found {}. Exiting.'.format(commit))
def gen_status(file_path): '''return generator with result of git status --porcelain''' all_status = git.status('--porcelain', file_path, _cwd=dir_path(file_path)) return all_status
print("load changes") git.pull("--all") git.reset("origin/master", "--hard") git.pull() print("Finish download") for i in l.split("\n")[1:]: if i and regex.search(i): ips.append(regex.search(i).groups()[0]) with open("rawlist.txt", "w") as fp: for i in ips: fp.write(i + "\n") with open("list.txt", 'w') as fp: # s = "[AutoProxy 0.2.9]\n" for i in ips: fp.write("||{}\n".format(i)) # s = base64.b64encode(s.encode('utf8')).decode() # for i in range(0, len(s), 64): # fp.write(s[i:i+64]) # fp.write("\n") if git.status("--short") != "": print("updating") git.add(".") git.commit("-m", "update by robot") git.push() print("updating finished")
"zephyr", "minimal", "esp8266", "pic16bit", "qemu-arm", "bare-arm", "rp2", ] for p in ports_to_delete: try: git.rm("-rf", "ports/" + p) except sh.ErrorReturnCode_128: pass # We inherit stm32 changes into stm because we did a git rename. git.status("--porcelain=1", "ports/stm", _out=out_buf) out_buf.seek(0) line = out_buf.readline() while line: state, path = line.split() if state == "UU": git.checkout("--ours", path) git.add(path) elif state == "UA": git.rm(path) line = out_buf.readline() # MicroPython added their nrf code in ports/nrf too. So, we always take our version. out_buf = StringIO() git.status("--porcelain=1", "ports/nrf", _out=out_buf) out_buf.seek(0)
print("load changes") git.pull("--all") git.reset("origin/master", "--hard") git.pull() print("Finish download") for i in l.split("\n")[1:]: if i and regex.search(i): ips.append(regex.search(i).groups()[0]) with open("rawlist.txt", "w") as fp: for i in ips: fp.write(i+"\n") with open("list.txt", 'w') as fp: # s = "[AutoProxy 0.2.9]\n" for i in ips: fp.write("||{}\n".format(i)) # s = base64.b64encode(s.encode('utf8')).decode() # for i in range(0, len(s), 64): # fp.write(s[i:i+64]) # fp.write("\n") if git.status("--short") != "": print("updating") git.add(".") git.commit("-m", "update by robot") git.push() print("updating finished")
def git_status(self): """Get current git status.""" cd(self.paths['root']) print git.status()
def push(remote_name, remote_branch, to_be_pushed_branch, commit_hash_list): git.status() current_branch = get_stdout(git('symbolic-ref', '--short', '-q', 'HEAD'))[0:-1] mark_message = '***mark***' # 校验是否tag已存在 tag_name = f"merging({current_branch}-->{remote_name}/{remote_branch})" code, output = subprocess.getstatusoutput(f"git tag | grep '^{tag_name}$'") if code == 0: print(f"错误,tag:{tag_name} 已存在") exit(-1) # 校验远程分支是否存在 code, output = subprocess.getstatusoutput('git fetch') if code != 0: print(output) print("fetch 失败") exit(-1) code, output = subprocess.getstatusoutput( f"git branch -r | cat | grep '^ *{remote_name}/{remote_branch}'") if code != 0: print("错误,远程分支%s不存在" % remote_branch) exit(-1) # 如果工作区不干净,mark提交 res = git.status() is_clean = re.match(".*nothing to commit, working tree clean.*", get_stdout(res), re.S) if not is_clean: print('工作区不干净,mark提交...') git.add('--all') git.commit('-a', '-m', mark_message) # 检出到远程临时分支 tmp_branch = f'tmp/local_{remote_name}_{remote_branch}' print(f'检出到远程临时分支"{tmp_branch}"...') git.checkout('-b', tmp_branch, f'{remote_name}/{remote_branch}') # cherry-pick try: print('开始cherry-pick...') res = git('cherry-pick', commit_hash_list) except sh.ErrorReturnCode_1: print(get_stderr(res)) print("请解决冲突,然后选择后续操作...") while True: operation = input('请输入处理方式') if operation == 0: print('execute: git cherry-pick --continue...') code, output = subprocess.getstatusoutput( 'git cherry-pick --continue') print(output) if code != 0: continue else: print('解决冲突成功') break elif operation == 1: print('退出,停在当前位置') git('check-pick', '--abort') exit(-1) elif operation == 2: print('撤销,回到起点...') git('check-pick', '--abort') # 切换会原来的分支,并去掉mark提交 git.switch(current_branch) git.branch('-D', tmp_branch) de_mark_commit(current_branch, mark_message) exit(-1) else: print('输入不合法,请重新输入') except ErrorReturnCode: print(get_stderr(res)) exit(-1) print('推送中...') git.push('-f', remote_name, f'HEAD:{to_be_pushed_branch}') # 切换会原来的分支,并去掉mark提交 print('切换会原来的分支,并去掉mark提交') git.switch(current_branch) git.branch('-D', tmp_branch) de_mark_commit(current_branch, mark_message) print(f'添加tag"{tag_name}"...') git.tag('-a', tag_name, '-m', "nothing") print('完成!')
def current_git_status(self): return git.status()
def add_to_blacklist(**kwargs): if 'windows' in str(platform.platform()).lower(): log('warning', "Git support not available in Windows.") return (False, "Git support not available in Windows.") blacklist = kwargs.get("blacklist", "") item_to_blacklist = kwargs.get("item_to_blacklist", "") username = kwargs.get("username", "") chat_profile_link = kwargs.get("chat_profile_link", "http://chat.stackexchange.com/users") code_permissions = kwargs.get("code_permissions", False) # Make sure git credentials are set up if git.config("--global", "--get", "user.name", _ok_code=[0, 1]) == "": return (False, "Tell someone to run `git config --global user.name \"SmokeDetector\"`") if git.config("--global", "--get", "user.email", _ok_code=[0, 1]) == "": return (False, "Tell someone to run `git config --global user.email \"[email protected]\"`") if blacklist == "": # If we broke the code, and this isn't assigned, error out before doing anything, but do # so gracefully with a nice error message. return (False, "Programming Error - Critical information missing for GitManager: blacklist") if item_to_blacklist == "": # If we broke the code, and this isn't assigned, error out before doing anything, but do # so gracefully with a nice error message. return (False, "Programming Error - Critical information missing for GitManager: item_to_blacklist") item_to_blacklist = item_to_blacklist.replace("\s", " ") if blacklist == "website": blacklist_file_name = "blacklisted_websites.txt" ms_search_option = "&body_is_regex=1&body=" elif blacklist == "keyword": blacklist_file_name = "bad_keywords.txt" ms_search_option = "&body_is_regex=1&body=" elif blacklist == "username": blacklist_file_name = "blacklisted_usernames.txt" ms_search_option = "&username_is_regex=1&username="******"Invalid blacklist type specified, something has broken badly!") git.checkout("master") try: git.pull() except: pass # Check that we're up-to-date with origin (GitHub) git.remote.update() if git("rev-parse", "refs/remotes/origin/master").strip() != git("rev-parse", "master").strip(): return (False, "HEAD isn't at tip of origin's master branch") # Check that blacklisted_websites.txt isn't modified locally. That could get ugly fast if blacklist_file_name in git.status(): # Also ugly return (False, "{0} is modified locally. This is probably bad.".format(blacklist_file_name)) # Add item to file with open(blacklist_file_name, "a+") as blacklist_file: last_character = blacklist_file.read()[-1:] if last_character != "\n": blacklist_file.write("\n") blacklist_file.write(item_to_blacklist + "\n") # Checkout a new branch (for PRs for non-code-privileged people) branch = "auto-blacklist-{0}".format(str(time.time())) git.checkout("-b", branch) # Clear HEAD just in case git.reset("HEAD") git.add(blacklist_file_name) git.commit("--author='SmokeDetector <*****@*****.**>'", "-m", u"Auto blacklist of {0} by {1} --autopull".format(item_to_blacklist, username)) if code_permissions: git.checkout("master") git.merge(branch) git.push("origin", "master") git.branch('-D', branch) # Delete the branch in the local git tree since we're done with it. else: git.push("origin", branch) git.checkout("master") if GlobalVars.github_username is None or GlobalVars.github_password is None: return (False, "Tell someone to set a GH password") payload = {"title": u"{0}: Blacklist {1}".format(username, item_to_blacklist), "body": u"[{0}]({1}) requests the blacklist of the {2} {3}. See the Metasmoke search [here]" "(https://metasmoke.erwaysoftware.com/search?utf8=%E2%9C%93{4}{5})\n" u"<!-- METASMOKE-BLACKLIST-{6} {3} -->".format(username, chat_profile_link, blacklist, item_to_blacklist, ms_search_option, item_to_blacklist.replace(" ", "+"), blacklist.upper()), "head": branch, "base": "master"} response = requests.post("https://api.github.com/repos/Charcoal-SE/SmokeDetector/pulls", auth=HTTPBasicAuth(GlobalVars.github_username, GlobalVars.github_password), data=json.dumps(payload)) log('debug', response.json()) try: git.checkout("deploy") # Return to deploy, pending the accept of the PR in Master. git.branch('-D', branch) # Delete the branch in the local git tree since we're done with it. return (True, "You don't have code privileges, but I've [created a pull request for you]({0}).".format( response.json()["html_url"])) except KeyError: git.checkout("deploy") # Return to deploy # Delete the branch in the local git tree, we'll create it again if the # command is run again. This way, we keep things a little more clean in # the local git tree git.branch('-D', branch) # Error capture/checking for any "invalid" GH reply without an 'html_url' item, # which will throw a KeyError. if "bad credentials" in str(response.json()['message']).lower(): # Capture the case when GH credentials are bad or invalid return (False, "Something is wrong with the GH credentials, tell someone to check them.") else: # Capture any other invalid response cases. return (False, "A bad or invalid reply was received from GH, the message was: %s" % response.json()['message']) git.checkout("deploy") # Return to deploy to await CI. return (True, "Blacklisted {0}".format(item_to_blacklist))
def current_git_status(): if 'windows' in str(platform.platform()).lower(): return "Git support not available in Windows." return git.status()