Example #1
0
// clMailMultiFlags extracts flags from the invocation of cl mail
// that should be passed on to the sub invocations of cl mail when
// operating across multiple repos.
// These are:
// -autosubmit, -cc, -d, -edit, -host, -m, -presubmit, remote-branch, -r,
// -set-topic, -topic, -check-uncommitted and -verify,
func clMailMultiFlags() []string {
	flags := []string{}
	stringFlag := func(name, value string) {
		if profilescmdline.IsFlagSet(cmdCLMail.ParsedFlags, name) {
			flags = append(flags, fmt.Sprintf("--%s=%s", name, value))
		}
	}
	boolFlag := func(name string, value bool) {
		if profilescmdline.IsFlagSet(cmdCLMail.ParsedFlags, name) {
			flags = append(flags, fmt.Sprintf("--%s=%t", name, value))
		}
	}

	// --edit is handled differently to other flags, if it is not
	// specifically set, the default is to run the editor once
	// and then reuse that message for the other parts of a multipart
	// CL - that is, set -edit=false for the other repos. If edit
	// is specifically set then that setting is used for all repos.
	// So using --edit=true allows for a different CL message in
	// each repo of a multipart CL.
	if profilescmdline.IsFlagSet(cmdCLMail.ParsedFlags, "edit") {
		// if --edit is set on the command line, use that value
		// for all subcommands
		flags = append(flags, fmt.Sprintf("--edit=%t", editFlag))
	} else {
		// if --edit is not set on the command line, use --edit=false
		// for subcommands.
		flags = append(flags, "--edit=false")
	}

	boolFlag("autosubmit", autosubmitFlag)
	stringFlag("cc", ccsFlag)
	boolFlag("d", draftFlag)
	stringFlag("host", hostFlag)
	stringFlag("m", messageFlag)
	stringFlag("presubmit", presubmitFlag)
	stringFlag("remote-branch", remoteBranchFlag)
	stringFlag("r", reviewersFlag)
	boolFlag("set-topic", setTopicFlag)
	boolFlag("check-uncommitted", uncommittedFlag)
	boolFlag("verify", verifyFlag)
	return flags
}
Example #2
0
func runp(jirix *jiri.X, cmd *cmdline.Command, args []string) error {
	hasUntrackedSet := profilescmdline.IsFlagSet(cmd.ParsedFlags, "has-untracked")
	hasUncommitedSet := profilescmdline.IsFlagSet(cmd.ParsedFlags, "has-uncommitted")
	hasGerritSet := profilescmdline.IsFlagSet(cmd.ParsedFlags, "has-gerrit-message")

	if runpFlags.interactive {
		runpFlags.collateOutput = false
	}

	var keysRE, branchRE *regexp.Regexp
	var err error

	if profilescmdline.IsFlagSet(cmd.ParsedFlags, "projects") {
		re := ""
		for _, pre := range strings.Split(runpFlags.projectKeys, ",") {
			re += pre + "|"
		}
		re = strings.TrimRight(re, "|")
		keysRE, err = regexp.Compile(re)
		if err != nil {
			return fmt.Errorf("failed to compile projects regexp: %q: %v", runpFlags.projectKeys, err)
		}
	}

	if profilescmdline.IsFlagSet(cmd.ParsedFlags, "has-branch") {
		branchRE, err = regexp.Compile(runpFlags.hasBranch)
		if err != nil {
			return fmt.Errorf("failed to compile has-branch regexp: %q: %v", runpFlags.hasBranch, err)
		}
	}

	for _, f := range []string{"show-key-prefix", "show-name-prefix"} {
		if profilescmdline.IsFlagSet(cmd.ParsedFlags, f) {
			if runpFlags.interactive && profilescmdline.IsFlagSet(cmd.ParsedFlags, "interactive") {
				fmt.Fprintf(jirix.Stderr(), "WARNING: interactive mode being disabled because %s was set\n", f)
			}
			runpFlags.interactive = false
			runpFlags.collateOutput = true
			break
		}
	}

	git := gitutil.New(jirix.NewSeq())
	homeBranch, err := git.CurrentBranchName()
	if err != nil {
		// jiri was run from outside of a project. Let's assume we'll
		// use all projects if none have been specified via the projects flag.
		if keysRE == nil {
			keysRE = regexp.MustCompile(".*")
		}
	}

	dirty := false
	if hasUntrackedSet || hasUncommitedSet {
		dirty = true
	}
	states, err := project.GetProjectStates(jirix, dirty)
	if err != nil {
		return err
	}
	mapInputs := map[project.ProjectKey]*mapInput{}
	var keys project.ProjectKeys
	for key, state := range states {
		if keysRE != nil {
			if !keysRE.MatchString(string(key)) {
				continue
			}
		} else {
			if state.CurrentBranch != homeBranch {
				continue
			}
		}
		if branchRE != nil {
			found := false
			for _, br := range state.Branches {
				if branchRE.MatchString(br.Name) {
					found = true
					break
				}
			}
			if !found {
				continue
			}
		}
		if hasUntrackedSet && (state.HasUntracked != runpFlags.hasUntracked) {
			continue
		}
		if hasUncommitedSet && (state.HasUncommitted != runpFlags.hasUncommitted) {
			continue
		}
		if hasGerritSet {
			hasMsg := false
			for _, br := range state.Branches {
				if (state.CurrentBranch == br.Name) && br.HasGerritMessage {
					hasMsg = true
					break
				}
			}
			if hasMsg != runpFlags.hasGerritMessage {
				continue
			}
		}
		mapInputs[key] = &mapInput{
			ProjectState: state,
			jirix:        jirix,
			key:          key,
		}
		keys = append(keys, key)
	}

	total := len(mapInputs)
	index := 1
	for _, mi := range mapInputs {
		mi.index = index
		mi.total = total
		index++
	}

	if runpFlags.verbose {
		fmt.Fprintf(jirix.Stdout(), "Project Names: %s\n", strings.Join(stateNames(mapInputs), " "))
		fmt.Fprintf(jirix.Stdout(), "Project Keys: %s\n", strings.Join(stateKeys(mapInputs), " "))
	}

	reader, err := profilesreader.NewReader(jirix, runpFlags.ProfilesMode, runpFlags.DBFilename)
	runner := &runner{
		reader: reader,
		args:   args,
	}
	mr := simplemr.MR{}
	if runpFlags.interactive {
		// Run one mapper at a time.
		mr.NumMappers = 1
		sort.Sort(keys)
	}
	in, out := make(chan *simplemr.Record, len(mapInputs)), make(chan *simplemr.Record, len(mapInputs))
	sigch := make(chan os.Signal)
	signal.Notify(sigch, os.Interrupt)
	go func() { <-sigch; mr.Cancel() }()
	go mr.Run(in, out, runner, runner)
	for _, key := range keys {
		in <- &simplemr.Record{string(key), []interface{}{mapInputs[key]}}
	}
	close(in)
	<-out
	return mr.Error()
}