def detect_scm_system(self, path, patch_directories=None): real_path = self._filesystem.realpath(path) if patch_directories == []: patch_directories = None if SVN.in_working_directory(real_path, executive=self._executive): return SVN(cwd=real_path, patch_directories=patch_directories, filesystem=self._filesystem, executive=self._executive) if Git.in_working_directory(real_path, executive=self._executive): return Git(cwd=real_path, patch_directories=patch_directories, filesystem=self._filesystem, executive=self._executive) if StubRepository.in_working_directory(real_path, filesystem=self._filesystem): return StubRepository(cwd=real_path, patch_directories=patch_directories, filesystem=self._filesystem, executive=self._executive) return None
def setUp(self): self.executive = Executive() self.filesystem = FileSystem() self.original_cwd = self.filesystem.getcwd() # Set up fresh git repository with one commit. self.untracking_checkout_path = self._mkdtemp( suffix='-git_unittest_untracking') self._run(['git', 'init', self.untracking_checkout_path]) self._chdir(self.untracking_checkout_path) self._write_text_file('foo_file', 'foo') self._run(['git', 'add', 'foo_file']) self._run(['git', 'commit', '-am', 'dummy commit']) self.untracking_scm = Git(cwd=self.untracking_checkout_path, filesystem=self.filesystem, executive=self.executive) # Then set up a second git repo that tracks the first one. self.tracking_git_checkout_path = self._mkdtemp( suffix='-git_unittest_tracking') self._run([ 'git', 'clone', '--quiet', self.untracking_checkout_path, self.tracking_git_checkout_path ]) self._chdir(self.tracking_git_checkout_path) self.tracking_scm = Git(cwd=self.tracking_git_checkout_path, filesystem=self.filesystem, executive=self.executive)
def __init__(self, tool, irc_password): SingleServerIRCBot.__init__(self, [(server, port, irc_password)], nickname, nickname) self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'quit': self.stop, }
def __init__(self, tool, announce_path, irc_password): SingleServerIRCBot.__init__(self, [(server, port, irc_password)], nickname, nickname) self.announce_path = announce_path self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'ping': self.ping, 'quit': self.stop, } self.last_commit = None
def checkout_test_repository(self, revision, url, directory): git = None if not self._filesystem.exists(directory): _log.info('Cloning %s into %s...' % (url, directory)) Git.clone(url, directory, self._host.executive) git = self.git(directory) elif self._options.fetch is True: git = self.git(directory) _log.info('Fetching %s...' % url) git.fetch() else: git = self.git(directory) _log.info('Checking out revision ' + revision) git.checkout(revision, not self._options.verbose)
def __init__(self, tool, announce_path, irc_password): SingleServerIRCBot.__init__(self, [(SERVER, PORT, irc_password)], NICKNAME, NICKNAME) self.announce_path = announce_path self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'ping': self.ping, 'quit': self.stop, } self.last_commit = None
def initialize_scm(self): # TODO(qyearsley): Refactor this so that scm is initialized # when self.scm() is called the first time; put any initialization # code in the git module. if sys.platform == 'win32': self._engage_awesome_windows_hacks() cwd = self.filesystem.abspath(self.filesystem.getcwd()) if Git.in_working_directory(cwd, executive=self.executive): self._scm = Git(cwd=cwd, filesystem=self.filesystem, executive=self.executive) return script_directory = self.filesystem.abspath( self.filesystem.dirname(self.filesystem.path_to_module(self.__module__))) _log.info('The current directory (%s) is not in a git repo, trying script directory %s.', cwd, script_directory) if Git.in_working_directory(script_directory, executive=self.executive): self._scm = Git(cwd=script_directory, filesystem=self.filesystem, executive=self.executive) return raise Exception('FATAL: Failed to find Git repo for %s or %s' % (cwd, script_directory))
class CommitAnnouncer(SingleServerIRCBot): _commit_detail_format = "%H\n%cn\n%s\n%b" # commit-sha1, author, subject, body def __init__(self, tool, irc_password): SingleServerIRCBot.__init__(self, [(server, port, irc_password)], nickname, nickname) self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'quit': self.stop, } def start(self): if not self._update(): return self.last_commit = self.git.latest_git_commit() SingleServerIRCBot.start(self) def post_new_commits(self): if not self.connection.is_connected(): return if not self._update(force_clean=True): self.stop("Failed to update repository!") return new_commits = self.git.git_commits_since(self.last_commit) if new_commits: self.last_commit = new_commits[-1] for commit in new_commits: commit_detail = self._commit_detail(commit) if commit_detail: _log.info('%s Posting commit %s' % (self._time(), commit)) self._post(commit_detail) else: _log.error('Malformed commit log for %s' % commit) # Bot commands. def help(self): self._post('Commands available: %s' % ' '.join(self.commands.keys())) def stop(self, message=""): self.connection.execute_delayed(0, lambda: self.die(message)) # IRC event handlers. def on_nicknameinuse(self, connection, event): connection.nick('%s_' % connection.get_nickname()) def on_welcome(self, connection, event): connection.join(channel) def on_pubmsg(self, connection, event): message = event.arguments()[0] command = self._message_command(message) if command: command() def _update(self, force_clean=False): if not self.git.is_cleanly_tracking_remote_master(): if not force_clean: confirm = raw_input('This repository has local changes, continue? (uncommitted changes will be lost) y/n: ') if not confirm.lower() == 'y': return False try: self.git.ensure_cleanly_tracking_remote_master() except ScriptError, e: _log.error('Failed to clean repository: %s' % e) return False attempts = 1 while attempts <= retry_attempts: if attempts > 1: # User may have sent a keyboard interrupt during the wait. if not self.connection.is_connected(): return False wait = int(update_wait_seconds) << (attempts - 1) if wait < 120: _log.info('Waiting %s seconds' % wait) else: _log.info('Waiting %s minutes' % (wait / 60)) time.sleep(wait) _log.info('Pull attempt %s out of %s' % (attempts, retry_attempts)) try: self.git.pull() return True except ScriptError, e: _log.error('Error pulling from server: %s' % e) _log.error('Output: %s' % e.output) attempts += 1
def git(self, test_repository): return Git(test_repository, None, executive=self._host.executive, filesystem=self._filesystem)
def scm_for_path(self, path): # FIXME: make scm() be a wrapper around this, and clean up the way # callers call initialize_scm() (to remove patch_directories) and scm(). if sys.platform == "win32": self._engage_awesome_windows_hacks() return Git(cwd=path, executive=self.executive, filesystem=self.filesystem)
class GitTestWithRealFilesystemAndExecutive(unittest.TestCase): def setUp(self): self.executive = Executive() self.filesystem = FileSystem() self.original_cwd = self.filesystem.getcwd() # Set up fresh git repository with one commit. self.untracking_checkout_path = self._mkdtemp( suffix='-git_unittest_untracking') self._run(['git', 'init', self.untracking_checkout_path]) self._chdir(self.untracking_checkout_path) self._write_text_file('foo_file', 'foo') self._run(['git', 'add', 'foo_file']) self._run(['git', 'commit', '-am', 'dummy commit']) self.untracking_scm = Git(cwd=self.untracking_checkout_path, filesystem=self.filesystem, executive=self.executive) # Then set up a second git repo that tracks the first one. self.tracking_git_checkout_path = self._mkdtemp( suffix='-git_unittest_tracking') self._run([ 'git', 'clone', '--quiet', self.untracking_checkout_path, self.tracking_git_checkout_path ]) self._chdir(self.tracking_git_checkout_path) self.tracking_scm = Git(cwd=self.tracking_git_checkout_path, filesystem=self.filesystem, executive=self.executive) def tearDown(self): self._chdir(self.original_cwd) self._run(['rm', '-rf', self.tracking_git_checkout_path]) self._run(['rm', '-rf', self.untracking_checkout_path]) def _join(self, *comps): return self.filesystem.join(*comps) def _chdir(self, path): self.filesystem.chdir(path) def _mkdir(self, path): assert not self.filesystem.exists(path) self.filesystem.maybe_make_directory(path) def _mkdtemp(self, **kwargs): return str(self.filesystem.mkdtemp(**kwargs)) def _remove(self, path): self.filesystem.remove(path) def _run(self, *args, **kwargs): return self.executive.run_command(*args, **kwargs) def _run_silent(self, args, **kwargs): self.executive.run_command(args, **kwargs) def _write_text_file(self, path, contents): self.filesystem.write_text_file(path, contents) def _write_binary_file(self, path, contents): self.filesystem.write_binary_file(path, contents) def _make_diff(self, command, *args): # We use this wrapper to disable output decoding. diffs should be treated as # binary files since they may include text files of multiple different encodings. return self._run([command, 'diff'] + list(args), decode_output=False) def _git_diff(self, *args): return self._make_diff('git', *args) def test_add_list(self): self._chdir(self.untracking_checkout_path) git = self.untracking_scm self._mkdir('added_dir') self._write_text_file('added_dir/added_file', 'new stuff') print self._run(['ls', 'added_dir']) print self._run(['pwd']) print self._run(['cat', 'added_dir/added_file']) git.add_list(['added_dir/added_file']) self.assertIn('added_dir/added_file', git.added_files()) def test_delete_recursively(self): self._chdir(self.untracking_checkout_path) git = self.untracking_scm self._mkdir('added_dir') self._write_text_file('added_dir/added_file', 'new stuff') git.add_list(['added_dir/added_file']) self.assertIn('added_dir/added_file', git.added_files()) git.delete_list(['added_dir/added_file']) self.assertNotIn('added_dir', git.added_files()) def test_delete_recursively_or_not(self): self._chdir(self.untracking_checkout_path) git = self.untracking_scm self._mkdir('added_dir') self._write_text_file('added_dir/added_file', 'new stuff') self._write_text_file('added_dir/another_added_file', 'more new stuff') git.add_list(['added_dir/added_file', 'added_dir/another_added_file']) self.assertIn('added_dir/added_file', git.added_files()) self.assertIn('added_dir/another_added_file', git.added_files()) git.delete_list(['added_dir/added_file']) self.assertIn('added_dir/another_added_file', git.added_files()) def test_exists(self): self._chdir(self.untracking_checkout_path) git = self.untracking_scm self._chdir(git.checkout_root) self.assertFalse(git.exists('foo.txt')) self._write_text_file('foo.txt', 'some stuff') self.assertFalse(git.exists('foo.txt')) git.add_list(['foo.txt']) git.commit_locally_with_message('adding foo') self.assertTrue(git.exists('foo.txt')) git.delete_list(['foo.txt']) git.commit_locally_with_message('deleting foo') self.assertFalse(git.exists('foo.txt')) def test_move(self): self._chdir(self.untracking_checkout_path) git = self.untracking_scm self._write_text_file('added_file', 'new stuff') git.add_list(['added_file']) git.move('added_file', 'moved_file') self.assertIn('moved_file', git.added_files()) def test_move_recursive(self): self._chdir(self.untracking_checkout_path) git = self.untracking_scm self._mkdir('added_dir') self._write_text_file('added_dir/added_file', 'new stuff') self._write_text_file('added_dir/another_added_file', 'more new stuff') git.add_list(['added_dir']) git.move('added_dir', 'moved_dir') self.assertIn('moved_dir/added_file', git.added_files()) self.assertIn('moved_dir/another_added_file', git.added_files()) def test_remote_branch_ref(self): # This tests a protected method. pylint: disable=protected-access self.assertEqual(self.tracking_scm._remote_branch_ref(), 'refs/remotes/origin/master') self._chdir(self.untracking_checkout_path) self.assertRaises(ScriptError, self.untracking_scm._remote_branch_ref) def test_create_patch(self): self._chdir(self.tracking_git_checkout_path) git = self.tracking_scm self._write_text_file('test_file_commit1', 'contents') self._run(['git', 'add', 'test_file_commit1']) git.commit_locally_with_message('message') git._patch_order = lambda: '' # pylint: disable=protected-access patch = git.create_patch() self.assertNotRegexpMatches(patch, r'Subversion Revision:') def test_patches_have_filenames_with_prefixes(self): self._chdir(self.tracking_git_checkout_path) git = self.tracking_scm self._write_text_file('test_file_commit1', 'contents') self._run(['git', 'add', 'test_file_commit1']) git.commit_locally_with_message('message') # Even if diff.noprefix is enabled, create_patch() produces diffs with prefixes. self._run(['git', 'config', 'diff.noprefix', 'true']) git._patch_order = lambda: '' # pylint: disable=protected-access patch = git.create_patch() self.assertRegexpMatches( patch, r'^diff --git a/test_file_commit1 b/test_file_commit1') def test_rename_files(self): self._chdir(self.tracking_git_checkout_path) git = self.tracking_scm git.move('foo_file', 'bar_file') git.commit_locally_with_message('message') def test_commit_position_from_git_log(self): # This tests a protected method. pylint: disable=protected-access git_log = """ commit 624c3081c0 Author: foobarbaz1 <*****@*****.**> Date: Mon Sep 28 19:10:30 2015 -0700 Test foo bar baz qux 123. BUG=000000 Review URL: https://codereview.chromium.org/999999999 Cr-Commit-Position: refs/heads/master@{#1234567} """ self._chdir(self.tracking_git_checkout_path) git = self.tracking_scm self.assertEqual(git._commit_position_from_git_log(git_log), 1234567) def test_timestamp_of_revision(self): # This tests a protected method. pylint: disable=protected-access self._chdir(self.tracking_git_checkout_path) git = self.tracking_scm position_regex = git._commit_position_regex_for_timestamp() git.most_recent_log_matching(position_regex, git.checkout_root)
def make_scm(self): scm = Git(cwd=".", executive=MockExecutive(), filesystem=MockFileSystem()) scm.read_git_config = lambda *args, **kw: "MOCKKEY:MOCKVALUE" return scm
class CommitAnnouncer(SingleServerIRCBot): _commit_detail_format = "%H\n%ae\n%s\n%b" # commit-sha1, author email, subject, body def __init__(self, tool, announce_path, irc_password): SingleServerIRCBot.__init__(self, [(SERVER, PORT, irc_password)], NICKNAME, NICKNAME) self.announce_path = announce_path self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'ping': self.ping, 'quit': self.stop, } self.last_commit = None def start(self): if not self._update(): return self.last_commit = self.git.latest_git_commit() SingleServerIRCBot.start(self) def post_new_commits(self): if not self.connection.is_connected(): return if not self._update(force_clean=True): self.stop("Failed to update repository!") return new_commits = self.git.git_commits_since(self.last_commit) if not new_commits: return self.last_commit = new_commits[-1] for commit in new_commits: if not self._should_announce_commit(commit): continue commit_detail = self._commit_detail(commit) if commit_detail: _log.info('%s Posting commit %s', self._time(), commit) _log.info('%s Posted message: %s', self._time(), repr(commit_detail)) self._post(commit_detail) else: _log.error('Malformed commit log for %s', commit) # Bot commands. def help(self): self._post('Commands available: %s' % ' '.join(self.commands.keys())) def ping(self): self._post('Pong.') def stop(self, message=""): self.connection.execute_delayed(0, lambda: self.die(message)) # IRC event handlers. Methods' arguments are determined by superclass # and some arguments maybe unused - pylint: disable=unused-argument def on_nicknameinuse(self, connection, event): connection.nick('%s_' % connection.get_nickname()) def on_welcome(self, connection, event): connection.join(CHANNEL) def on_pubmsg(self, connection, event): message = event.arguments()[0] command = self._message_command(message) if command: command() def _update(self, force_clean=False): if not self.git.is_cleanly_tracking_remote_master(): if not force_clean: confirm = raw_input( 'This repository has local changes, continue? (uncommitted changes will be lost) y/n: ' ) if not confirm.lower() == 'y': return False try: self.git.ensure_cleanly_tracking_remote_master() except ScriptError as e: _log.error('Failed to clean repository: %s', e) return False attempts = 1 while attempts <= RETRY_ATTEMPTS: if attempts > 1: # User may have sent a keyboard interrupt during the wait. if not self.connection.is_connected(): return False wait = int(UPDATE_WAIT_SECONDS) << (attempts - 1) if wait < 120: _log.info('Waiting %s seconds', wait) else: _log.info('Waiting %s minutes', wait / 60) time.sleep(wait) _log.info('Pull attempt %s out of %s', attempts, RETRY_ATTEMPTS) try: self.git.pull(timeout_seconds=PULL_TIMEOUT_SECONDS) return True except ScriptError as e: _log.error('Error pulling from server: %s', e) _log.error('Output: %s', e.output) attempts += 1 _log.error('Exceeded pull attempts') _log.error('Aborting at time: %s', self._time()) return False def _time(self): return time.strftime('[%x %X %Z]', time.localtime()) def _message_command(self, message): prefix = '%s:' % self.connection.get_nickname() if message.startswith(prefix): command_name = message[len(prefix):].strip() if command_name in self.commands: return self.commands[command_name] return None def _should_announce_commit(self, commit): return any( path.startswith(self.announce_path) for path in self.git.affected_files(commit)) def _commit_detail(self, commit): return self._format_commit_detail( self.git.git_commit_detail(commit, self._commit_detail_format)) def _format_commit_detail(self, commit_detail): if commit_detail.count('\n') < self._commit_detail_format.count('\n'): return '' commit, email, subject, body = commit_detail.split('\n', 3) commit_position_re = r'^Cr-Commit-Position: refs/heads/master@\{#(?P<commit_position>\d+)\}' commit_position = None red_flag_strings = ['NOTRY=true', 'TBR='] red_flags = [] for line in body.split('\n'): match = re.search(commit_position_re, line) if match: commit_position = match.group('commit_position') for red_flag_string in red_flag_strings: if line.lower().startswith(red_flag_string.lower()): red_flags.append(line.strip()) url = 'https://crrev.com/%s' % (commit_position if commit_position else commit[:8]) red_flag_message = '\x037%s\x03' % ( ' '.join(red_flags)) if red_flags else '' return ('%s %s committed "%s" %s' % (url, email, subject, red_flag_message)).strip() def _post(self, message): self.connection.execute_delayed( 0, lambda: self.connection.privmsg(CHANNEL, self._sanitize_string(message))) def _sanitize_string(self, message): return message.encode('ascii', 'backslashreplace')
class CommitAnnouncer(SingleServerIRCBot): _commit_detail_format = "%H\n%ae\n%s\n%b" # commit-sha1, author email, subject, body def __init__(self, tool, announce_path, irc_password): SingleServerIRCBot.__init__(self, [(SERVER, PORT, irc_password)], NICKNAME, NICKNAME) self.announce_path = announce_path self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'ping': self.ping, 'quit': self.stop, } self.last_commit = None def start(self): if not self._update(): return self.last_commit = self.git.latest_git_commit() SingleServerIRCBot.start(self) def post_new_commits(self): if not self.connection.is_connected(): return if not self._update(force_clean=True): self.stop("Failed to update repository!") return new_commits = self.git.git_commits_since(self.last_commit) if not new_commits: return self.last_commit = new_commits[-1] for commit in new_commits: if not self._should_announce_commit(commit): continue commit_detail = self._commit_detail(commit) if commit_detail: _log.info('%s Posting commit %s', self._time(), commit) _log.info('%s Posted message: %s', self._time(), repr(commit_detail)) self._post(commit_detail) else: _log.error('Malformed commit log for %s', commit) # Bot commands. def help(self): self._post('Commands available: %s' % ' '.join(self.commands.keys())) def ping(self): self._post('Pong.') def stop(self, message=""): self.connection.execute_delayed(0, lambda: self.die(message)) # IRC event handlers. Methods' arguments are determined by superclass # and some arguments maybe unused - pylint: disable=unused-argument def on_nicknameinuse(self, connection, event): connection.nick('%s_' % connection.get_nickname()) def on_welcome(self, connection, event): connection.join(CHANNEL) def on_pubmsg(self, connection, event): message = event.arguments()[0] command = self._message_command(message) if command: command() def _update(self, force_clean=False): if not self.git.is_cleanly_tracking_remote_master(): if not force_clean: confirm = raw_input('This repository has local changes, continue? (uncommitted changes will be lost) y/n: ') if not confirm.lower() == 'y': return False try: self.git.ensure_cleanly_tracking_remote_master() except ScriptError as e: _log.error('Failed to clean repository: %s', e) return False attempts = 1 while attempts <= RETRY_ATTEMPTS: if attempts > 1: # User may have sent a keyboard interrupt during the wait. if not self.connection.is_connected(): return False wait = int(UPDATE_WAIT_SECONDS) << (attempts - 1) if wait < 120: _log.info('Waiting %s seconds', wait) else: _log.info('Waiting %s minutes', wait / 60) time.sleep(wait) _log.info('Pull attempt %s out of %s', attempts, RETRY_ATTEMPTS) try: self.git.pull(timeout_seconds=PULL_TIMEOUT_SECONDS) return True except ScriptError as e: _log.error('Error pulling from server: %s', e) _log.error('Output: %s', e.output) attempts += 1 _log.error('Exceeded pull attempts') _log.error('Aborting at time: %s', self._time()) return False def _time(self): return time.strftime('[%x %X %Z]', time.localtime()) def _message_command(self, message): prefix = '%s:' % self.connection.get_nickname() if message.startswith(prefix): command_name = message[len(prefix):].strip() if command_name in self.commands: return self.commands[command_name] return None def _should_announce_commit(self, commit): return any(path.startswith(self.announce_path) for path in self.git.affected_files(commit)) def _commit_detail(self, commit): return self._format_commit_detail(self.git.git_commit_detail(commit, self._commit_detail_format)) def _format_commit_detail(self, commit_detail): if commit_detail.count('\n') < self._commit_detail_format.count('\n'): return '' commit, email, subject, body = commit_detail.split('\n', 3) commit_position_re = r'^Cr-Commit-Position: refs/heads/master@\{#(?P<commit_position>\d+)\}' commit_position = None red_flag_strings = ['NOTRY=true', 'TBR='] red_flags = [] for line in body.split('\n'): match = re.search(commit_position_re, line) if match: commit_position = match.group('commit_position') for red_flag_string in red_flag_strings: if line.lower().startswith(red_flag_string.lower()): red_flags.append(line.strip()) url = 'https://crrev.com/%s' % (commit_position if commit_position else commit[:8]) red_flag_message = '\x037%s\x03' % (' '.join(red_flags)) if red_flags else '' return ('%s %s committed "%s" %s' % (url, email, subject, red_flag_message)).strip() def _post(self, message): self.connection.execute_delayed(0, lambda: self.connection.privmsg(CHANNEL, self._sanitize_string(message))) def _sanitize_string(self, message): return message.encode('ascii', 'backslashreplace')
class CommitAnnouncer(SingleServerIRCBot): _commit_detail_format = "%H\n%ae\n%s\n%b" # commit-sha1, author email, subject, body def __init__(self, tool, announce_path, irc_password): SingleServerIRCBot.__init__(self, [(server, port, irc_password)], nickname, nickname) self.announce_path = announce_path self.git = Git(cwd=tool.scm().checkout_root, filesystem=tool.filesystem, executive=tool.executive) self.commands = { 'help': self.help, 'quit': self.stop, } def start(self): if not self._update(): return self.last_commit = self.git.latest_git_commit() SingleServerIRCBot.start(self) def post_new_commits(self): if not self.connection.is_connected(): return if not self._update(force_clean=True): self.stop("Failed to update repository!") return new_commits = self.git.git_commits_since(self.last_commit) if not new_commits: return self.last_commit = new_commits[-1] for commit in new_commits: if not self._should_announce_commit(commit): continue commit_detail = self._commit_detail(commit) if commit_detail: _log.info('%s Posting commit %s' % (self._time(), commit)) _log.info('%s Posted message: %s' % (self._time(), repr(commit_detail))) self._post(commit_detail) else: _log.error('Malformed commit log for %s' % commit) # Bot commands. def help(self): self._post('Commands available: %s' % ' '.join(self.commands.keys())) def stop(self, message=""): self.connection.execute_delayed(0, lambda: self.die(message)) # IRC event handlers. def on_nicknameinuse(self, connection, event): connection.nick('%s_' % connection.get_nickname()) def on_welcome(self, connection, event): connection.join(channel) def on_pubmsg(self, connection, event): message = event.arguments()[0] command = self._message_command(message) if command: command() def _update(self, force_clean=False): if not self.git.is_cleanly_tracking_remote_master(): if not force_clean: confirm = raw_input( 'This repository has local changes, continue? (uncommitted changes will be lost) y/n: ' ) if not confirm.lower() == 'y': return False try: self.git.ensure_cleanly_tracking_remote_master() except ScriptError, e: _log.error('Failed to clean repository: %s' % e) return False attempts = 1 while attempts <= retry_attempts: if attempts > 1: # User may have sent a keyboard interrupt during the wait. if not self.connection.is_connected(): return False wait = int(update_wait_seconds) << (attempts - 1) if wait < 120: _log.info('Waiting %s seconds' % wait) else: _log.info('Waiting %s minutes' % (wait / 60)) time.sleep(wait) _log.info('Pull attempt %s out of %s' % (attempts, retry_attempts)) try: self.git.pull() return True except ScriptError, e: _log.error('Error pulling from server: %s' % e) _log.error('Output: %s' % e.output) attempts += 1
def make_scm(self): git = Git(cwd='.', executive=MockExecutive(), filesystem=MockFileSystem()) git.read_git_config = lambda *args, **kw: 'MOCKKEY:MOCKVALUE' return git