// Refresh advises the review tool that the code being reviewed has changed, and to reload it. // // This corresponds to calling the diffusion.looksoon API. func (arc Arcanist) Refresh(repo repository.Repo) { // We cannot determine the repo's callsign (the identifier Phabricator uses for the repo) // in all cases, but we can figure it out in the case that the mirror runs on the same // directories that Phabricator is using. In that scenario, the repo directories default // to being named "/var/repo/<CALLSIGN>", so if the repo path starts with that prefix then // we can try to strip out that prefix and use the rest as a callsign. if strings.HasPrefix(repo.GetPath(), defaultRepoDirPrefix) { possibleCallsign := strings.TrimPrefix(repo.GetPath(), defaultRepoDirPrefix) request := lookSoonRequest{Callsigns: []string{possibleCallsign}} response := make(map[string]interface{}) runArcCommandOrDie("diffusion.looksoon", request, &response) } }
func mirrorRepoToReview(repo repository.Repo, tool review.Tool, syncToRemote bool) { if syncToRemote { if err := repo.PullUpdates(); err != nil { log.Printf("Failed to pull updates for the repo %v: %v\n", repo, err) return } } stateHash := repo.GetRepoStateHash() if processedStates[repo.GetPath()] != stateHash { log.Print("Mirroring repo: ", repo) for _, revision := range repo.ListNotedRevisions(request.Ref) { existingComments[revision] = comment.ParseAllValid(repo.GetNotes(comment.Ref, revision)) for _, req := range request.ParseAllValid(repo.GetNotes(request.Ref, revision)) { tool.EnsureRequestExists(repo, revision, req, existingComments[revision]) } } openReviews[repo.GetPath()] = tool.ListOpenReviews(repo) processedStates[repo.GetPath()] = stateHash tool.Refresh(repo) } for _, review := range openReviews[repo.GetPath()] { if reviewCommit := review.GetFirstCommit(repo); reviewCommit != nil { log.Println("Processing review: ", *reviewCommit) revisionComments := getExistingComments(*reviewCommit) log.Printf("Loaded %d comments for %v\n", len(revisionComments), *reviewCommit) for _, c := range review.LoadComments() { if !hasOverlap(c, revisionComments) { // The comment is new. note, err := c.Write() if err != nil { log.Fatal(err) } log.Printf("Appending a comment: %s", string(note)) repo.AppendNote(comment.Ref, *reviewCommit, note, c.Author) } else { log.Printf("Skipping '%v', as it has already been written\n", c) } } } } if syncToRemote { if err := repo.PushUpdates(); err != nil { log.Printf("Failed to push updates to the repo %v: %v\n", repo, err) } } }
// createDifferentialDiff generates a Phabricator resource that represents a diff between two revisions. // // The generated resource includes metadata about how the diff was generated, and a JSON representation // of the changes from the diff, as parsed by Phabricator. func (arc Arcanist) createDifferentialDiff(repo repository.Repo, mergeBase, revision repository.Revision, req request.Request, priorDiffs []string) (*differentialDiff, error) { revisionDetails, err := repo.GetDetails(revision) if err != nil { return nil, err } changes, err := arc.getDiffChanges(repo, mergeBase, revision) if err != nil { return nil, err } createRequest := differentialCreateDiffRequest{ Branch: abbreviateRefName(req.ReviewRef), SourceControlSystem: "git", SourceControlBaseRevision: string(mergeBase), SourcePath: repo.GetPath(), LintStatus: "4", // Status code 5 means "linter skipped" UnitStatus: "4", // Status code 5 means "unit tests have been skipped" Changes: changes, } var createResponse differentialCreateDiffResponse runArcCommandOrDie("differential.creatediff", createRequest, &createResponse) if createResponse.Error != "" { return nil, fmt.Errorf(createResponse.ErrorMessage) } localCommits := make(map[string]interface{}) for _, priorDiff := range priorDiffs { diffID, err := strconv.Atoi(priorDiff) if err != nil { return nil, err } queryRequest := differentialQueryDiffsRequest{[]int{diffID}} var queryResponse differentialQueryDiffsResponse runArcCommandOrDie("differential.querydiffs", queryRequest, &queryResponse) if queryResponse.Error != "" { return nil, fmt.Errorf(queryResponse.ErrorMessage) } priorProperty := queryResponse.Response[priorDiff].Properties if priorPropertyMap, ok := priorProperty.(map[string]interface{}); ok { if localCommitsProperty, ok := priorPropertyMap["local:commits"]; ok { if priorLocalCommits, ok := localCommitsProperty.(map[string]interface{}); ok { for id, val := range priorLocalCommits { localCommits[id] = val } } } } } localCommits[string(revision)] = *revisionDetails localCommitsProperty, err := json.Marshal(localCommits) if err != nil { return nil, err } if err := arc.setDiffProperty(createResponse.Response.ID, "local:commits", string(localCommitsProperty)); err != nil { return nil, err } if err := arc.setDiffProperty(createResponse.Response.ID, "arc:unit", "{}"); err != nil { return nil, err } return &createResponse.Response, nil }