def Run(params): base_branch = params.args[1] repos_and_local_branches = GetReposAndLocalBranches( params, patterns=['*%s*' % base_branch]) # Now, do things the other way, show a connection from the branch to the repos which have it! branch_to_repos = ConvertRepoToBranchesToBranchToRepos( repos_and_local_branches) if len(params.config.repos) == 1: params.config.serial = True if base_branch in branch_to_repos or not branch_to_repos: # Ok, the default one matches, just go on with it... from .action_default import Run return Run(params) if len(branch_to_repos) == 1: # The default one does not match but we have a single match, let's use it! branch, _repo = iteritems(branch_to_repos).next() params.args[1] = branch from .action_default import Run # @Reimport return Run(params) # Print it for the user Print( 'Found more than one branch that matches ${START_COLOR}%s${RESET_COLOR}:\n' % params.args[1]) PrintBranchToRepos(branch_to_repos, params) Print( '\n${START_COLOR}ERROR${RESET_COLOR}: unable to decide branch to work on.', __color__='RED')
def Run(params): base_branch = params.args[1] repos_and_local_branches = GetReposAndLocalBranches( params, patterns=['*%s*' % base_branch]) # Now, do things the other way, show a connection from the branch to the repos which have it! branch_to_repos = ConvertRepoToBranchesToBranchToRepos(repos_and_local_branches) if len(params.config.repos) == 1: params.config.serial = True if base_branch in branch_to_repos or not branch_to_repos: # Ok, the default one matches, just go on with it... from .action_default import Run return Run(params) if len(branch_to_repos) == 1: # The default one does not match but we have a single match, let's use it! branch, _repo = iteritems(branch_to_repos).next() params.args[1] = branch from .action_default import Run # @Reimport return Run(params) # Print it for the user Print('Found more than one branch that matches ${START_COLOR}%s${RESET_COLOR}:\n' % params.args[1]) PrintBranchToRepos(branch_to_repos, params) Print('\n${START_COLOR}ERROR${RESET_COLOR}: unable to decide branch to work on.', __color__='RED')
def CreateMessagesFromReposToBranchAndMessages(repos, repos_to_branch_and_messages): from mu_repo.backwards import iteritems from mu_repo.print_ import CreateJoinedReposMsg messages = [] empty_repos_and_branches = [] for repo in repos: branch, message = repos_to_branch_and_messages.get( repo, ("ERROR: Unable to get cache state", "ERROR: Unable to get cache state") ) if message: messages.append(message) else: empty_repos_and_branches.append((repo, branch)) if empty_repos_and_branches: branch_to_repos = {} for repo, branch in empty_repos_and_branches: branch_to_repos.setdefault(branch, []).append(repo) for branch, repos in iteritems(branch_to_repos): messages.append( "${START_COLOR}Unchanged:${RESET_COLOR} %s\nat branch: ${START_COLOR}%s${RESET_COLOR}\n" % (CreateJoinedReposMsg("", repos), branch) ) return messages
def __init__(self): colors = dict( BLACK=[], BLUE=['BLUE'], CYAN=['GREEN', 'BLUE'], GREEN=['GREEN'], MAGENTA=['RED', 'BLUE'], RED=['RED'], WHITE=['RED', 'GREEN', 'BLUE'], YELLOW=['RED', 'GREEN'], ) self._foreground_map = color_map = { '' : 0 } for color_name, color_components in iteritems(colors): if color_components: value = _color_console.FOREGROUND_INTENSITY else: value = 0 for component in color_components: value |= getattr(_color_console, 'FOREGROUND_' + component) color_map[color_name] = value #Some of the calls below could raise exceptions, in which case we should #fallback to another approach! self._reset = _color_console.get_text_attr()
def __init__(self): import win32console colors = dict( BLACK=[], BLUE=['BLUE'], CYAN=['GREEN', 'BLUE'], GREEN=['GREEN'], MAGENTA=['RED', 'BLUE'], RED=['RED'], WHITE=['RED', 'GREEN', 'BLUE'], YELLOW=['RED', 'GREEN'], ) self._foreground_map = color_map = { '' : 0 } for color_name, color_components in iteritems(colors): if color_components: value = getattr(win32console, 'FOREGROUND_INTENSITY') else: value = 0 for component in color_components: value |= getattr(win32console, 'FOREGROUND_' + component) color_map[color_name] = value #Some of the calls below could raise exceptions, in which case we should #fallback to another approach! self._output_handle = win32console.GetStdHandle(win32console.STD_OUTPUT_HANDLE) self._reset = self._output_handle.GetConsoleScreenBufferInfo()['Attributes'] self._console = win32console.PyConsoleScreenBufferType(self._output_handle)
def PrintBranchToRepos(branch_to_repos, params): for branch, repos in sorted(iteritems(branch_to_repos)): if len(repos) == 1: msg = '${START_COLOR}%s${RESET_COLOR}' % (branch,) elif len(repos) == len(set(params.config.repos)): msg = '${START_COLOR}%s${RESET_COLOR} (all repos)' % (branch,) else: msg = '${START_COLOR}%s${RESET_COLOR} (%s)' % (branch, ', '.join(sorted(repos))) Print(msg)
def PrintBranchToRepos(branch_to_repos, params): for branch, repos in sorted(iteritems(branch_to_repos)): if len(repos) == 1: msg = '${START_COLOR}%s${RESET_COLOR}' % (branch, ) elif len(repos) == len(set(params.config.repos)): msg = '${START_COLOR}%s${RESET_COLOR} (all repos)' % (branch, ) else: msg = '${START_COLOR}%s${RESET_COLOR} (%s)' % (branch, ', '.join( sorted(repos))) Print(msg)
def Run(params): #Update them from .action_up import Run repos_and_curr_branch = Run(params) if not repos_and_curr_branch: Print('No tracked repos!') return branch_to_repos = {} #Check if all on the same branch for repo, branch in repos_and_curr_branch: curr = branch_to_repos.setdefault(branch, []) curr.append(repo) if len(branch_to_repos) > 1: msg = '\n${START_COLOR}Warning: found repos in different branches${RESET_COLOR}:\n %s\nProceed?(y/n)' % ( '\n '.join([ str('Branch: ${START_COLOR}%s${RESET_COLOR} (%s)' % (key, ', '.join(val))) for (key, val) in branch_to_repos.items() ])) ret = '' while ret not in ('y', 'n'): Print(msg) ret = raw_input().strip().lower() if ret != 'y': return #Diff it from .action_diff import Run #@Reimport initial_args = params.args[:] initial_repos = params.config.repos[:] for branch, repos in iteritems(branch_to_repos): params.args = initial_args + ['origin/' + branch] params.config.repos = repos if len(branch_to_repos) > 1: Print('\nOutput for branch: ${START_COLOR}%s${RESET_COLOR} (%s)' % (branch, ', '.join(repos))) Run(params) params.args = initial_args params.config.repos = initial_repos
def Run(params): ''' Note: this action always runs in parallel. ''' repos_and_curr_branch = GetReposAndCurrBranch(params, verbose=False) as_dict = dict(repos_and_curr_branch) commands = [] for repo, _branch in repos_and_curr_branch: commands.append(ParallelCmd(repo, [params.config.git] + ['status', '-s'])) empty_repos_and_branches = [] def OnOutput(output): branch_name = as_dict.get(output.repo, 'UNKNOWN_BRANCH') if not output.stdout: empty_repos_and_branches.append((output.repo, branch_name)) else: status = [ START_COLOR, output.repo, ' ', branch_name, ':', RESET_COLOR, '\n', Indent(output.stdout), '\n', ] Print(''.join(status)) ExecuteInParallel(commands, on_output=OnOutput) if empty_repos_and_branches: branch_to_repos = {} for repo, branch in empty_repos_and_branches: branch_to_repos.setdefault(branch, []).append(repo) for branch, repos in iteritems(branch_to_repos): Print("${START_COLOR}Unchanged:${RESET_COLOR} %s\nat branch: ${START_COLOR}%s${RESET_COLOR}\n" % ( CreateJoinedReposMsg('', repos), branch)) return repos_and_curr_branch
def Run(params): #Update them from .action_up import Run repos_and_curr_branch = Run(params) if not repos_and_curr_branch: Print('No tracked repos!') return branch_to_repos = {} #Check if all on the same branch for repo, branch in repos_and_curr_branch: curr = branch_to_repos.setdefault(branch, []) curr.append(repo) if len(branch_to_repos) > 1: msg = '\n${START_COLOR}Warning: found repos in different branches${RESET_COLOR}:\n %s\nProceed?(y/n)' % ('\n '.join([str('Branch: ${START_COLOR}%s${RESET_COLOR} (%s)' % (key, ', '.join(val))) for (key, val) in branch_to_repos.items()])) ret = '' while ret not in ('y', 'n'): Print(msg) ret = raw_input().strip().lower() if ret != 'y': return #Diff it from .action_diff import Run #@Reimport initial_args = params.args[:] initial_repos = params.config.repos[:] for branch, repos in iteritems(branch_to_repos): params.args = initial_args + ['origin/' + branch] params.config.repos = repos if len(branch_to_repos) > 1: Print('\nOutput for branch: ${START_COLOR}%s${RESET_COLOR} (%s)' % (branch, ', '.join(repos))) Run(params) params.args = initial_args params.config.repos = initial_repos
def __str__(self): lst = [] for key, val in self.items(): if isinstance(val, str): lst.append('%s=%s' % (key, val)) elif isinstance(val, list): assert key[-1] == 's' # (change repos->repo or remote_hosts->remote_host) key = key[:-1] for v in sorted(val): lst.append('%s=%s' % (key, v)) elif isinstance(val, dict): assert key == 'groups' for group_name, repos in sorted(iteritems(val)): values = [group_name] + repos lst.append('group=%s' % ', '.join(values)) else: raise AssertionError('Expecting val to be a list of strings.') return '\n'.join(lst)
def __str__(self): lst = [] for key, val in self.items(): if isinstance(val, str): lst.append('%s=%s' % (key, val)) elif isinstance(val, list): assert key == 'repos' key = key[:-1] for v in sorted(val): lst.append('%s=%s' % (key, v)) elif isinstance(val, dict): assert key == 'groups' for group_name, repos in sorted(iteritems(val)): values = [group_name] + repos lst.append('group=%s' % ', '.join(values)) else: raise AssertionError('Expecting val to be a list of strings.') return '\n'.join(lst)
def GetReposAndCurrBranch(params, verbose=True): ''' :param params: Params The parameters used to get the repos and current branch (mostly using config). :return: list(tuple(str, str)) A list with the repository and current branch for that repository. ''' repos_and_curr_branch = [] def OnOutput(output): stdout = output.stdout.strip() if stdout: repos_and_curr_branch.append((output.repo, stdout)) else: if verbose: Print( 'Unable to update (could not get current branch for: %s)' % (output.repo, )) from .action_default import Run #@Reimport from mu_repo import Params old_serial = params.config.serial params.config.serial = False #Cannot be serial as we want to get the output Run(Params(params.config, ['rev-parse', '--abbrev-ref', 'HEAD'], params.config_file), on_output=OnOutput) if verbose: branch_to_repos = {} for repo, branch in repos_and_curr_branch: branch_to_repos.setdefault(branch, []).append(repo) for branch, repos in iteritems(branch_to_repos): Print( "Will handle ${START_COLOR}origin %s${RESET_COLOR} for: %s\n" % (branch, ', '.join(sorted(repos)))) #Restore serial for next command. params.config.serial = old_serial return repos_and_curr_branch
def GetReposAndCurrBranch(params, verbose=True): ''' :param params: Params The parameters used to get the repos and current branch (mostly using config). :return: list(tuple(str, str)) A list with the repository and current branch for that repository. ''' repos_and_curr_branch = [] def OnOutput(output): stdout = output.stdout.strip() if stdout: repos_and_curr_branch.append((output.repo, stdout)) else: if verbose: Print('Unable to update (could not get current branch for: %s)' % (output.repo,)) from .action_default import Run #@Reimport from mu_repo import Params old_serial = params.config.serial params.config.serial = False #Cannot be serial as we want to get the output Run( Params(params.config, ['rev-parse', '--abbrev-ref', 'HEAD'], params.config_file), on_output=OnOutput ) if verbose: branch_to_repos = {} for repo, branch in repos_and_curr_branch: branch_to_repos.setdefault(branch, []).append(repo) for branch, repos in iteritems(branch_to_repos): Print("Will handle ${START_COLOR}origin %s${RESET_COLOR} for: %s\n" % ( branch, ', '.join(sorted(repos)))) #Restore serial for next command. params.config.serial = old_serial return repos_and_curr_branch
def CreateMessagesFromReposToBranchAndMessages(repos, repos_to_branch_and_messages): from mu_repo.backwards import iteritems from mu_repo.print_ import CreateJoinedReposMsg messages = [] empty_repos_and_branches = [] for repo in repos: branch, message = repos_to_branch_and_messages.get( repo, ('ERROR: Unable to get cache state', 'ERROR: Unable to get cache state')) if message: messages.append(message) else: empty_repos_and_branches.append((repo, branch)) if empty_repos_and_branches: branch_to_repos = {} for repo, branch in empty_repos_and_branches: branch_to_repos.setdefault(branch, []).append(repo) for branch, repos in iteritems(branch_to_repos): messages.append( "${START_COLOR}Unchanged:${RESET_COLOR} %s\nat branch: ${START_COLOR}%s${RESET_COLOR}\n" % ( CreateJoinedReposMsg('', repos), branch)) return messages
def Run(params): ''' Actions for mu group. ''' args = params.args config_file = params.config_file config = params.config msgs = [] command = args[1] if len(args) > 1 else None group_name = args[2] if len(args) > 2 else None clean_new_group = '--clean' in args or '--empty' in args if command != 'add' and clean_new_group: msg = '--clean and --empty only for "add" command' Print(msg) return Status(msg, False) if not command: if not config.groups: msg = 'No groups registered. Use "add" to add a new one.' Print(msg) msgs.append(msg) else: for group_name in config.groups: if group_name == config.current_group: msg = '* %s' % group_name else: msg = ' %s' % group_name Print(msg) msgs.append(msg) elif command == 'add': if group_name is None: msg = 'Group name not given.' Print(msg) return Status(msg, False) if group_name in config.groups: msg = 'Group ${START_COLOR}%s${RESET_COLOR} already exists.' % group_name Print(msg) return Status(msg, False) if clean_new_group: config.groups[group_name] = [] else: config.groups[group_name] = config.repos config.current_group = group_name elif command in ('rm', 'del', 'switch', 'sw'): if group_name is None: header_msg = 'Please choose which group you want to switch to:' while True: Print(header_msg) groups = set() i_to_group = {} lines = [] for i, (group, group_contents) in enumerate(sorted(backwards.iteritems(config.groups))): groups_desc = ', '.join(group_contents) lines.append(('[${START_COLOR}%s${RESET_COLOR}]: %s' % (i, group), groups_desc)) i_to_group[str(i)] = group groups.add(group) discount_len = len('${START_COLOR}') + len('${RESET_COLOR}') max_part_0 = 0 for line in lines: max_part_0 = max(max_part_0, len(line[0])-discount_len) max_part_0+= 1 max_cols = 80 remainder = max_cols - max_part_0 if remainder < 20: remainder = 20 part0_size = max_cols - remainder for part0, part1 in lines: if (len(part0) - discount_len) < part0_size: part0 += ' ' * (part0_size - (len(part0) - discount_len)) if len(part1) > remainder: part1 = part1[:remainder-3] + '...' Print(part0+part1) Print('\n[${START_COLOR}C${RESET_COLOR}]: Cancel') try: user_entered = raw_input('\nSelect: ').strip() except KeyboardInterrupt: return Status('Cancelled', False) if user_entered in i_to_group: group_name = i_to_group[user_entered] break if user_entered in groups: group_name = user_entered break if user_entered in ('C', 'c'): return Status('Cancelled', False) header_msg = 'Did not match. Please choose again:' if group_name not in config.groups: msg = 'Group "%s" does not exist.' % group_name Print(msg) return Status(msg, False) if command in ('switch', 'sw'): msg = 'Switched to group ${START_COLOR}%s${RESET_COLOR}' % group_name config.current_group = group_name else: msg = 'Group ${START_COLOR}%s${RESET_COLOR} removed' % group_name if config.current_group == group_name: config.current_group = None msg += ' (no current group)' msg += '.' del config.groups[group_name] Print(msg) msgs.append(msg) elif command == 'reset': config.current_group = None msg = 'Group reset. No current group.' Print(msg) msgs.append(msg) else: msg = 'Unknown group command: %s' % command Print(msg) return Status(msg, False) with open(config_file, 'w') as f: f.write(str(config)) return Status('\n'.join(msgs), True, config)