// Run runs the analyzers that this driver knows about on the provided ShipshapeRequest, // taking configuration into account. func (sd ShipshapeDriver) Run(ctx server.Context, in *rpcpb.ShipshapeRequest, out chan<- *rpcpb.ShipshapeResponse) error { var ars []*rpcpb.AnalyzeResponse log.Printf("Received analysis request for event %v, stage %v, categories %v, repo %v", *in.Event, *in.Stage, in.TriggeredCategory, *in.ShipshapeContext.RepoRoot) // However we exit, send back the set of collected AnalyzeResponses // TODO(ciera): we should be streaming back the responses, not sending them all at the end. defer func() { out <- &rpcpb.ShipshapeResponse{ AnalyzeResponse: ars, } }() if in.ShipshapeContext.RepoRoot == nil { return fmt.Errorf("No repo root was set") } root := *in.ShipshapeContext.RepoRoot // cd into the root directory orgDir, restore, err := file.ChangeDir(root) if err != nil { log.Printf("Could not change into directory %s from base %s", root, orgDir) ars = append(ars, generateFailure("Driver setup", fmt.Sprint(err))) return err } defer func() { if err := restore(); err != nil { log.Printf("could not return back into %s from %s: %v", orgDir, root, err) } }() cfg, err := loadConfig(configFilename, *in.Event) if err != nil { log.Print("error loading config") // TODO(collinwinter): attach the error to the config file. ars = append(ars, generateFailure("Driver setup", err.Error())) return err } // Get the list of all categories sd.serviceMap = sd.getAllServiceInfo() allCats := sd.allCats() // Use the triggered categories if specified var desiredCats strset.Set if len(in.TriggeredCategory) > 0 { desiredCats = strset.New(in.TriggeredCategory...) } else if cfg != nil { desiredCats = strset.New(cfg.categories...) if len(desiredCats) > 0 { log.Printf("Running with categories from .shipshape file: %s" + desiredCats.String()) } else if *in.Event != defaults.DefaultEvent { return fmt.Errorf("No categories configured for event %s", *in.Event) } } if len(desiredCats) == 0 { log.Printf("No categories specified, running with default categories: %s", sd.defaultCategories.String()) desiredCats = sd.defaultCategories } // Find out what categories we have available, and remove/warn on the missing ones missingCats := strset.New().AddSet(desiredCats).RemoveSet(allCats) for missing := range missingCats { ars = append(ars, generateFailure(missing, fmt.Sprintf("The triggered category %q could not be found at the locations %v", missing, sd.AnalyzerLocations))) } desiredCats = desiredCats.RemoveSet(missingCats) if len(desiredCats) == 0 { log.Printf("No categories configured to run, doing nothing") return nil } // TODO(ciera): move this global ignore stuff into the CLI processing ignorePaths := []string{} if cfg != nil { ignorePaths = cfg.ignore } // Fill in the file_paths if they are empty in the context context := proto.Clone(in.ShipshapeContext).(*contextpb.ShipshapeContext) context.FilePath, err = retrieveAndFilterFiles(*context.RepoRoot, context.FilePath, ignorePaths) if err != nil { log.Printf("Had problems accessing files: %v", err.Error()) ars = append(ars, generateFailure("Driver setup", fmt.Sprint(err))) return err } if len(context.FilePath) == 0 { log.Print("No files to run on, doing nothing") return nil } // TODO(ciera): rather than pass the stage through here and checking all analyzers, // filter out the stages earlier, when we check categories stage := contextpb.Stage_PRE_BUILD if in.Stage != nil { stage = *in.Stage } log.Printf("Analyzing stage %s", stage.String()) if stage == contextpb.Stage_PRE_BUILD { ars = append(ars, sd.callAllAnalyzers(desiredCats, context, stage)...) } /*else { comps := filepath.Join(*context.RepoRoot, compilationsDir) compUnits, err := findCompilationUnits(comps) log.Printf("Found %d compUnits at %s", len(compUnits), comps) if err != nil { log.Printf("Could not retrieve compilation units: %v", err) ars = append(ars, generateFailure("Driver setup", err.Error())) return nil } for path, compUnit := range compUnits { context.CompilationDetails = &contextpb.CompilationDetails{ CompilationUnit: compUnit, CompilationDescriptionPath: proto.String(path), } log.Printf("Calling services with comp unit at %s", path) ars = append(ars, sd.callAllAnalyzers(desiredCats, context, stage)...) } } */ log.Print("Analysis completed") return nil }
func isSubset(a, b strset.Set) bool { return len(a.Intersect(b)) == len(a) }