// projectStates returns a map with all projects that are on the same // current branch as the current project, as well as a slice of their // project keys sorted lexicographically. Unless "allowdirty" is true, // an error is returned if any matching project has uncommitted changes. // The keys are returned, sorted, to avoid the caller having to recreate // the them by iterating over the map. func projectStates(jirix *jiri.X, allowdirty bool) (map[project.ProjectKey]*project.ProjectState, project.ProjectKeys, error) { git := gitutil.New(jirix.NewSeq()) branch, err := git.CurrentBranchName() if err != nil { return nil, nil, err } states, err := project.GetProjectStates(jirix, false) if err != nil { return nil, nil, err } uncommitted := []string{} var keys project.ProjectKeys for _, s := range states { if s.CurrentBranch == branch { key := s.Project.Key() fullState, err := project.GetProjectState(jirix, key, true) if err != nil { return nil, nil, err } if !allowdirty && fullState.HasUncommitted { uncommitted = append(uncommitted, string(key)) } else { keys = append(keys, key) } } } if len(uncommitted) > 0 { return nil, nil, fmt.Errorf("the following projects have uncommitted changes: %s", strings.Join(uncommitted, ", ")) } members := map[project.ProjectKey]*project.ProjectState{} for _, key := range keys { members[key] = states[key] } if len(members) == 0 { return nil, nil, nil } sort.Sort(keys) return members, keys, nil }
// runProjectInfo provides structured info on local projects. func runProjectInfo(jirix *jiri.X, args []string) error { tmpl, err := template.New("info").Parse(formatFlag) if err != nil { return fmt.Errorf("failed to parse template %q: %v", formatFlag, err) } regexps := []*regexp.Regexp{} if len(args) > 0 { regexps = make([]*regexp.Regexp, len(args), len(args)) for i, a := range args { re, err := regexp.Compile(a) if err != nil { return fmt.Errorf("failed to compile regexp %v: %v", a, err) } regexps[i] = re } } dirty := false for _, slow := range []string{"HasUncommitted", "HasUntracked"} { if strings.Contains(formatFlag, slow) { dirty = true break } } var states map[project.ProjectKey]*project.ProjectState var keys project.ProjectKeys if len(args) == 0 { currentProjectKey, err := project.CurrentProjectKey(jirix) if err != nil { return err } state, err := project.GetProjectState(jirix, currentProjectKey, true) if err != nil { // jiri was run from outside of a project so let's // use all available projects. states, err = project.GetProjectStates(jirix, dirty) if err != nil { return err } for key := range states { keys = append(keys, key) } } else { states = map[project.ProjectKey]*project.ProjectState{ currentProjectKey: state, } keys = append(keys, currentProjectKey) } } else { var err error states, err = project.GetProjectStates(jirix, dirty) if err != nil { return err } for key := range states { for _, re := range regexps { if re.MatchString(string(key)) { keys = append(keys, key) break } } } } sort.Sort(keys) for _, key := range keys { state := states[key] out := &bytes.Buffer{} if err = tmpl.Execute(out, state); err != nil { return jirix.UsageErrorf("invalid format") } fmt.Fprintln(jirix.Stdout(), out.String()) } return nil }