def _GetRemoteHosts(self): remote_hosts = self._remote_hosts if remote_hosts is None: # Lazily-calculate (and then cache it). git = self.git from mu_repo.execute_command import ExecuteCommand output = ExecuteCommand( [git] + 'config --get-regexp mu-repo.remote-base-url'.split(), '.', return_stdout=True) remotes_hosts = [] for line in output.splitlines(): if line.startswith('mu-repo.remote-base-url '): line = line[len('mu-repo.remote-base-url '):] remotes_hosts.append(line) self._remote_hosts = remotes_hosts return self._remote_hosts
def Run(params): ''' This action will grab the latest version of mu-repo from the repository. ''' import mu_repo import os.path repo_dir = os.path.dirname(os.path.dirname(mu_repo.__file__)) if not os.path.exists(os.path.join(repo_dir, '.git')): Print( 'Can only automatically update mu-repo if it was properly gotten from a git repository.' ) return config = params.config git = config.git or 'git' ExecuteCommand([git, 'pull', '--rebase'], repo=repo_dir)
def _Clone(remote, repo, params, other_cmd_line_args): created_dir = os.path.join('.', repo) if os.path.exists(os.path.join(created_dir, '.git')): # If it already exists, bail out! Print( 'Skipping clone of: ${START_COLOR}%s${RESET_COLOR} because it already exists.' % (repo, )) return True remote_path = remote if not remote_path.endswith('/') and not remote_path.endswith('\\'): remote_path += '/' git = params.config.git ExecuteCommand([git, 'clone', '%s%s' % (remote_path, repo)] + other_cmd_line_args, '.') if os.path.exists(os.path.join(created_dir, '.git')): return True return False
def Run(params): ''' This action applies a pull request from github in a new branch. There can be no changes in the current repo. To execute: mu github-pull user/repo.git:branch Will do the following: git checkout -b branch-pull-request git pull https://github.com/user/repo.git branch git checkout initial_branch git merge branch-pull-request --no-commit --no-ff ''' config = params.config if len(config.repos) != 1: Print('Can only apply pull request for a single repo.') return if len(params.args) < 2: Print( 'Expecting at least 1 argument. E.g.: user/repo.git:branch_to_merge' ) return user_repo_and_branch = params.args[1] splitted = user_repo_and_branch.split(':') if len(splitted) != 2: Print('Expected: user/repo.git:branch. Received: %s' % (user_repo_and_branch)) return user_repo, user_branch = splitted user = user_repo.split('/')[0] repo = iter(config.repos).next() git = config.git or 'git' cmd = [git, 'status', '--porcelain'] stdout = ExecuteCommand(cmd, repo, return_stdout=True) if stdout: Print( 'Unable to execute because there are changes in the working directory:\n', stdout) return repos_and_curr_branch = GetReposAndCurrBranch(params) if len(repos_and_curr_branch) != 1: Print('Must find a single repo with current branch. Found: %s' % (repos_and_curr_branch, )) return _local_repo, local_branch = repos_and_curr_branch[0] local_pull_request_branch = user_branch + '-' + user + '-pull-request' ExecuteCommand([git, 'checkout', '-b', local_pull_request_branch], '.') ExecuteCommand( [git, 'pull', 'https://github.com/' + user_repo, user_branch], '.') # Exec([git, 'checkout', local_branch]) # Exec([git, 'merge', local_pull_request_branch, '--no-commit', '--no-ff']) msg = '\n'.join([ '\n$If all went well, do:', '${START_COLOR}mu dd${RESET_COLOR} to see changes, then: ', '${START_COLOR}mu ac${RESET_COLOR} to commit changes (if all is OK): ', 'To discard/forget this merge, do:', '${START_COLOR}mu reset --hard${RESET_COLOR}', '${START_COLOR}mu branch -D %s${RESET_COLOR}' % (local_pull_request_branch, ), 'To merge this request:', '${START_COLOR}mu checkout %s${RESET_COLOR}' % (local_branch, ), '${START_COLOR}mu merge %s --no-commit --no-ff${RESET_COLOR}' % (local_pull_request_branch, ), ]) Print(msg)
def Run(params): ''' This is the first action that should be run in a new mu installation. It'll ask for common things to configure git properly. Things not done here but which the user should still do: Set: GIT_SSH to point to plink.exe (and have pageant with the key already loaded). ''' git = params.config.git or 'git' from mu_repo.execute_command import ExecuteCommand #--- Name user_name = raw_input('User name:').strip() if user_name: ExecuteCommand([git] + 'config --global user.name'.split() + [user_name], '.') else: Print('Skipping user.name configuration.') #--- E-mail user_email = raw_input('\nUser e-mail:').strip() if user_email: ExecuteCommand([git] + 'config --global user.email'.split() + [user_email], '.') else: Print('Skipping user.email configuration.') #--- Auto-crlf auto_crlf = raw_input( '\nAuto-crlf handling (default false, options: false, true, input):' ).strip().lower() if not auto_crlf: auto_crlf = 'false' if auto_crlf in ('false', 'true', 'input'): ExecuteCommand([git] + 'config --global core.autocrlf'.split() + [auto_crlf], '.') else: Print( 'Skipping core.autocrlf configuration (input: "%s" not recognized).' % (auto_crlf, )) config_date = raw_input( '\nConfig format.pretty for one line and set default to short? (default: y, options: y, n)' ).strip().lower() if not config_date: config_date = 'y' if config_date == 'y': ExecuteCommand([git] + [ 'config', '--global', 'format.pretty', '%h %ad %Cgreen%aN%Creset %s' ], '.') ExecuteCommand([git] + 'config --global log.date short'.split(), '.') wrap = raw_input( '\nShow logs wrapped? (i.e.: set less -r): (default: y, options: y, n)' ).strip().lower() if not wrap: wrap = 'y' if wrap == 'y': ExecuteCommand([git, 'config', '--global', 'core.pager', 'less -r'], '.') wrap = raw_input( '\nCreate aliases? (default: y, options: y, n)').strip().lower() if not wrap: wrap = 'y' if wrap == 'y': ExecuteCommand([git, 'config', '--global', 'alias.st', 'status -s'], '.') ExecuteCommand([ git, 'config', '--global', 'alias.create-branch', 'checkout -b ' ], '.')
def Run(params): ''' Submit to reviewboard Note: must have already committed the work. By default will do a diff from the current_branch to origin/current_branch. Note: reviewboard must be already configured: mu config reviewboard.url http://reviewboard.hdqt.appcelerator.com/ Options: #-o: open browser #-g: guess description and title Maybe in the future we could support: #--server=http://reviewboard.hdqt.appcelerator.com/ #--diff-filename= Should do: d:\bin\Python265\Scripts\post-review.exe -g -o --branch=development --tracking-branch=origin/development --bugs-closed=4654 --target-groups=Studio d:\bin\Python265\Scripts\post-review -g -o --diff-filename=mycode.diff --bugs-closed=4654 --target-groups=Studio ''' args = params.args dirty_flag = False for arg in args: if arg == '--dirty': dirty_flag = True args.remove(arg) break if len(args) < 3: Print( '''Expecting 2 parameters: bugs_closed and target_groups (i.e.: mu post-review 4689 Studio) Optional: --dirty: to post a review while there are changes in the working dir.''' ) return bug_closed = args[1] target_group = args[2] repos_and_curr_branch = GetReposAndCurrBranch(params) repos_with_changes = ComputeReposWithChanges(repos_and_curr_branch, params) if not dirty_flag: changed = [ repo for repo, has_change in repos_with_changes.items() if has_change ] if changed: Print( '''Unable to post review. All the contents must be committed before generating a review. Note: pass '--dirty' flag to commit with changed resources (will still get changes from branch origin/branch). Changed repos: %s''' % (' '.join(changed), )) return repos_with_changes = ComputeReposWithChangesFromCurrentBranchToOrigin( repos_and_curr_branch, params) if not repos_with_changes: Print( 'Unable to post review. Did not detect change in any repository.') return Print('Posting review for repos: %s ' % (' '.join(repos_with_changes), )) as_dict = dict(repos_and_curr_branch) for repo in repos_with_changes: branch = as_dict[repo] try: ExecuteCommand( [ 'post-review', '-g', '-o', '--branch=' + branch, '--tracking-branch=origin/' + branch, '--bugs-closed=' + bug_closed, '--target-groups=' + target_group, ], repo, return_stdout=False, verbose=True, ) except: Print( 'Some error happened executing the post-review command. Please check if it is in your PATH.' ) return
def Run(params, add, commit, push): from .print_ import Print, CreateJoinedReposMsg args = params.args[1:] if push: force_push=False for force_flag in ('--force', '-f'): if force_flag in args: args.remove(force_flag) force_push = True if commit and not args: git = params.config.git from mu_repo.execute_command import ExecuteCommand output = ExecuteCommand( [git] + 'config --get-regexp editor'.split(), '.', return_stdout=True) editors = [] for line in output.splitlines(): if line.startswith(b'core.editor '): line = line[len(b'core.editor '):] editors.append(line) if not editors: Print('Message for commit is required for git add -A & git commit -m command (or git core.editor must be configured).') return else: import tempfile import subprocess with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as f: f.write(b'\n\n') f.write(b'# Please enter the commit message for your changes. Lines starting\n') f.write(b'# with "#" will be ignored, and an empty message aborts the commit.\n') import sys args = editors[0].decode(sys.getfilesystemencoding()) # Handle having something as: git config core.editor "'C:\Program File\Notepad++\notepad++.exe' -multiInst -notabbar -nosession -noPlugin" # where we have to replace ' for " so that the command can be properly recognized by the shell. if sys.platform == 'win32': args = args.replace(u'\'', u'"') args += u' ' filename = f.name if isinstance(filename, bytes): filename = filename.decode(sys.getfilesystemencoding()) args += filename if hasattr(subprocess, 'run'): subprocess.run(args) else: subprocess.call(args) with open(f.name, 'r') as stream: lines = [x for x in stream.read().strip().splitlines() if not x.startswith('#')] contents = '\n'.join(lines) import os os.remove(f.name) if not contents: Print('Commit message not provided. Commit aborted.') return else: args = [contents] from .execute_parallel_command import ParallelCmd, ExecuteInParallelStackingMessages serial = params.config.serial if add: commands = [ParallelCmd(repo, [params.config.git, 'add', '-A']) for repo in params.config.repos] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip(), lambda repos: Print(CreateJoinedReposMsg('Executed "git add -A" in:', repos)), serial=serial, ) if commit: commit_msg = ' '.join(args) commands = [ParallelCmd(repo, [params.config.git, 'commit', '-m', commit_msg]) for repo in params.config.repos] ExecuteInParallelStackingMessages( commands, lambda output: 'nothing to commit (working directory clean)' in output.stdout, lambda repos: Print(CreateJoinedReposMsg('Nothing to commit at:', repos)), serial=serial, ) if push: from .get_repos_and_curr_branch import GetReposAndCurrBranch repos_and_curr_branch = GetReposAndCurrBranch(params) if force_push: force_args = ['--force'] else: force_args = [] commands = [ParallelCmd(repo, [params.config.git, 'push', 'origin', branch] + force_args) for (repo, branch) in repos_and_curr_branch] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip() and output.stderr.strip() == 'Everything up-to-date', lambda repos: Print(CreateJoinedReposMsg('Up-to-date:', repos)), serial=serial, )
def Run(params, add, commit, push): from .print_ import Print, CreateJoinedReposMsg args = params.args[1:] if commit and not args: git = params.config.git from mu_repo.execute_command import ExecuteCommand output = ExecuteCommand([git] + 'config --get-regexp editor'.split(), '.', return_stdout=True) editors = [] for line in output.splitlines(): if line.startswith(b'core.editor '): line = line[len(b'core.editor '):] editors.append(line) if not editors: Print( 'Message for commit is required for git add -A & git commit -m command (or git core.editor must be configured).' ) return else: import tempfile import subprocess with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as f: f.write(b'\n\n') f.write( b'# Please enter the commit message for your changes. Lines starting\n' ) f.write( b'# with "#" will be ignored, and an empty message aborts the commit.\n' ) import sys args = editors[0].decode( sys.getfilesystemencoding()) + ' ' + f.name if hasattr(subprocess, 'run'): subprocess.run(args) else: subprocess.call(args) with open(f.name, 'r') as stream: lines = [ x for x in stream.read().strip().splitlines() if not x.startswith('#') ] contents = '\n'.join(lines) import os os.remove(f.name) if not contents: Print('Commit message not provided. Commit aborted.') return else: args = [contents] from .execute_parallel_command import ParallelCmd, ExecuteInParallelStackingMessages serial = params.config.serial if add: commands = [ ParallelCmd(repo, [params.config.git, 'add', '-A']) for repo in params.config.repos ] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip(), lambda repos: Print( CreateJoinedReposMsg('Executed "git add -A" in:', repos)), serial=serial, ) if commit: commit_msg = ' '.join(args) commands = [ ParallelCmd(repo, [params.config.git, 'commit', '-m', commit_msg]) for repo in params.config.repos ] ExecuteInParallelStackingMessages( commands, lambda output: 'nothing to commit (working directory clean)' in output.stdout, lambda repos: Print( CreateJoinedReposMsg('Nothing to commit at:', repos)), serial=serial, ) if push: from .get_repos_and_curr_branch import GetReposAndCurrBranch repos_and_curr_branch = GetReposAndCurrBranch(params) commands = [ ParallelCmd(repo, [params.config.git, 'push', 'origin', branch]) for (repo, branch) in repos_and_curr_branch ] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip() and output.stderr.strip() == 'Everything up-to-date', lambda repos: Print(CreateJoinedReposMsg('Up-to-date:', repos)), serial=serial, )
def Run(params, add, commit, push): from .print_ import Print, CreateJoinedReposMsg args = params.args[1:] if push: force_push = False for force_flag in ('--force', '-f'): if force_flag in args: args.remove(force_flag) force_push = True if commit and not args: git = params.config.git from mu_repo.execute_command import ExecuteCommand output = ExecuteCommand([git] + 'config --get-regexp editor'.split(), '.', return_stdout=True) editors = [] for line in output.splitlines(): if line.startswith(b'core.editor '): line = line[len(b'core.editor '):] editors.append(line) if not editors: Print( 'Message for commit is required for git add -A & git commit -m command (or git core.editor must be configured).' ) return else: import tempfile import subprocess with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as f: f.write(b'\n\n') f.write( b'# Please enter the commit message for your changes. Lines starting\n' ) f.write( b'# with "#" will be ignored, and an empty message aborts the commit.\n' ) import sys args = editors[0].decode(sys.getfilesystemencoding()) # Handle having something as: git config core.editor "'C:\Program File\Notepad++\notepad++.exe' -multiInst -notabbar -nosession -noPlugin" # where we have to replace ' for " so that the command can be properly recognized by the shell. if sys.platform == 'win32': args = args.replace(u'\'', u'"') args += u' ' filename = f.name if isinstance(filename, bytes): filename = filename.decode(sys.getfilesystemencoding()) args += filename if hasattr(subprocess, 'run'): subprocess.run(args) else: subprocess.call(args) with open(f.name, 'r') as stream: lines = [ x for x in stream.read().strip().splitlines() if not x.startswith('#') ] contents = '\n'.join(lines) import os os.remove(f.name) if not contents: Print('Commit message not provided. Commit aborted.') return else: args = [contents] from .execute_parallel_command import ParallelCmd, ExecuteInParallelStackingMessages serial = params.config.serial if add: commands = [ ParallelCmd(repo, [params.config.git, 'add', '-A']) for repo in params.config.repos ] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip(), lambda repos: Print( CreateJoinedReposMsg('Executed "git add -A" in:', repos)), serial=serial, ) if commit: commit_msg = ' '.join(args) commands = [ ParallelCmd(repo, [params.config.git, 'commit', '-m', commit_msg]) for repo in params.config.repos ] ExecuteInParallelStackingMessages( commands, lambda output: 'nothing to commit (working directory clean)' in output.stdout, lambda repos: Print( CreateJoinedReposMsg('Nothing to commit at:', repos)), serial=serial, ) if push: from .get_repos_and_curr_branch import GetReposAndCurrBranch repos_and_curr_branch = GetReposAndCurrBranch(params) if force_push: force_args = ['--force'] else: force_args = [] commands = [ ParallelCmd(repo, [params.config.git, 'push', 'origin', branch] + force_args) for (repo, branch) in repos_and_curr_branch ] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip() and output.stderr.strip() == 'Everything up-to-date', lambda repos: Print(CreateJoinedReposMsg('Up-to-date:', repos)), serial=serial, )
def Run(params, add, commit, push): from .print_ import Print, CreateJoinedReposMsg args = params.args[1:] if commit and not args: git = params.config.git from mu_repo.execute_command import ExecuteCommand output = ExecuteCommand( [git] + 'config --get-regexp editor'.split(), '.', return_stdout=True) editors = [] for line in output.splitlines(): if line.startswith(b'core.editor '): line = line[len(b'core.editor '):] editors.append(line) if not editors: Print('Message for commit is required for git add -A & git commit -m command (or git core.editor must be configured).') return else: import tempfile import subprocess with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as f: f.write(b'\n\n') f.write(b'# Please enter the commit message for your changes. Lines starting\n') f.write(b'# with "#" will be ignored, and an empty message aborts the commit.\n') import sys args = editors[0].decode(sys.getfilesystemencoding()) + ' ' + f.name if hasattr(subprocess, 'run'): subprocess.run(args) else: subprocess.call(args) with open(f.name, 'r') as stream: lines = [x for x in stream.read().strip().splitlines() if not x.startswith('#')] contents = '\n'.join(lines) import os os.remove(f.name) if not contents: Print('Commit message not provided. Commit aborted.') return else: args = [contents] from .execute_parallel_command import ParallelCmd, ExecuteInParallelStackingMessages serial = params.config.serial if add: commands = [ParallelCmd(repo, [params.config.git, 'add', '-A']) for repo in params.config.repos] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip(), lambda repos: Print(CreateJoinedReposMsg('Executed "git add -A" in:', repos)), serial=serial, ) if commit: commit_msg = ' '.join(args) commands = [ParallelCmd(repo, [params.config.git, 'commit', '-m', commit_msg]) for repo in params.config.repos] ExecuteInParallelStackingMessages( commands, lambda output: 'nothing to commit (working directory clean)' in output.stdout, lambda repos: Print(CreateJoinedReposMsg('Nothing to commit at:', repos)), serial=serial, ) if push: from .get_repos_and_curr_branch import GetReposAndCurrBranch repos_and_curr_branch = GetReposAndCurrBranch(params) commands = [ParallelCmd(repo, [params.config.git, 'push', 'origin', branch]) for (repo, branch) in repos_and_curr_branch] ExecuteInParallelStackingMessages( commands, lambda output: not output.stdout.strip() and output.stderr.strip() == 'Everything up-to-date', lambda repos: Print(CreateJoinedReposMsg('Up-to-date:', repos)), serial=serial, )