Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The LUCI Authors. All rights reserved. | 1 // Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package buildbot | 5 package buildbot |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 sort.Strings(groupNames) | 373 sort.Strings(groupNames) |
| 374 for _, k := range groupNames { | 374 for _, k := range groupNames { |
| 375 group := groups[k] | 375 group := groups[k] |
| 376 // Also take this oppertunity to sort the properties within the groups. | 376 // Also take this oppertunity to sort the properties within the groups. |
| 377 sort.Sort(group) | 377 sort.Sort(group) |
| 378 result = append(result, group) | 378 result = append(result, group) |
| 379 } | 379 } |
| 380 return | 380 return |
| 381 } | 381 } |
| 382 | 382 |
| 383 type bbFile struct { | |
|
nodir
2017/04/19 18:37:48
what is this? i don't see its usage
hinoka
2017/04/20 22:09:43
Oops, this wasn't supposed to be here.
| |
| 384 Name string `json:"name"` | |
| 385 Url interface{} `json:"url"` | |
| 386 } | |
| 387 | |
| 383 // blame extracts the commit and blame information from a buildbot build and | 388 // blame extracts the commit and blame information from a buildbot build and |
| 384 // returns it as a list of Commits. | 389 // returns it as a list of Commits. |
| 385 func blame(b *buildbotBuild) (result []*resp.Commit) { | 390 func blame(b *buildbotBuild) (result []*resp.Commit) { |
| 386 for _, c := range b.Sourcestamp.Changes { | 391 for _, c := range b.Sourcestamp.Changes { |
| 387 » » files := make([]string, len(c.Files)) | 392 » » files := c.GetFiles() |
| 388 » » for i, f := range c.Files { | |
| 389 » » » // Buildbot stores files both as a string, or as a dict with a single entry | |
| 390 » » » // named "name". It doesn't matter to us what the type is, but we need | |
| 391 » » » // to reflect on the type anyways. | |
| 392 » » » if fn, ok := f.(string); ok { | |
| 393 » » » » files[i] = fn | |
| 394 » » » } else if fn, ok := f.(struct{ Name string }); ok { | |
| 395 » » » » files[i] = fn.Name | |
| 396 » » » } | |
| 397 » » } | |
| 398 result = append(result, &resp.Commit{ | 393 result = append(result, &resp.Commit{ |
| 399 AuthorEmail: c.Who, | 394 AuthorEmail: c.Who, |
| 400 Repo: c.Repository, | 395 Repo: c.Repository, |
| 401 » » » Revision: c.Revision, | 396 » » » CommitTime: time.Unix(int64(c.When), 0), |
| 397 » » » Revision: &resp.Link{ | |
| 398 » » » » URL: c.Revlink, | |
| 399 » » » » Label: c.Revision, | |
| 400 » » » }, | |
| 402 Description: c.Comments, | 401 Description: c.Comments, |
| 403 Title: strings.Split(c.Comments, "\n")[0], | 402 Title: strings.Split(c.Comments, "\n")[0], |
| 404 File: files, | 403 File: files, |
| 405 }) | 404 }) |
| 406 } | 405 } |
| 407 return | 406 return |
| 408 } | 407 } |
| 409 | 408 |
| 410 // sourcestamp extracts the source stamp from various parts of a buildbot build, | 409 // sourcestamp extracts the source stamp from various parts of a buildbot build, |
| 411 // including the properties. | 410 // including the properties. |
| 412 func sourcestamp(c context.Context, b *buildbotBuild) *resp.SourceStamp { | 411 func sourcestamp(c context.Context, b *buildbotBuild) *resp.SourceStamp { |
| 413 ss := &resp.SourceStamp{} | 412 ss := &resp.SourceStamp{} |
| 414 rietveld := "" | 413 rietveld := "" |
| 414 got_revision := "" | |
| 415 repository := "" | |
| 415 issue := int64(-1) | 416 issue := int64(-1) |
| 416 // TODO(hinoka): Gerrit URLs. | 417 // TODO(hinoka): Gerrit URLs. |
| 417 for _, prop := range b.Properties { | 418 for _, prop := range b.Properties { |
| 418 switch prop.Name { | 419 switch prop.Name { |
| 419 case "rietveld": | 420 case "rietveld": |
| 420 if v, ok := prop.Value.(string); ok { | 421 if v, ok := prop.Value.(string); ok { |
| 421 rietveld = v | 422 rietveld = v |
| 422 } else { | 423 } else { |
| 423 logging.Warningf(c, "Field rietveld is not a str ing: %#v", prop.Value) | 424 logging.Warningf(c, "Field rietveld is not a str ing: %#v", prop.Value) |
| 424 } | 425 } |
| 425 case "issue": | 426 case "issue": |
| 426 if v, ok := prop.Value.(float64); ok { | 427 if v, ok := prop.Value.(float64); ok { |
| 427 issue = int64(v) | 428 issue = int64(v) |
| 428 } else { | 429 } else { |
| 429 logging.Warningf(c, "Field issue is not a float: %#v", prop.Value) | 430 logging.Warningf(c, "Field issue is not a float: %#v", prop.Value) |
| 430 } | 431 } |
| 431 | 432 |
| 432 case "got_revision": | 433 case "got_revision": |
| 433 if v, ok := prop.Value.(string); ok { | 434 if v, ok := prop.Value.(string); ok { |
| 434 » » » » ss.Revision = v | 435 » » » » got_revision = v |
| 435 } else { | 436 } else { |
| 436 logging.Warningf(c, "Field got_revision is not a string: %#v", prop.Value) | 437 logging.Warningf(c, "Field got_revision is not a string: %#v", prop.Value) |
| 437 } | 438 } |
| 438 | 439 |
| 440 case "repository": | |
| 441 if v, ok := prop.Value.(string); ok { | |
| 442 repository = v | |
| 443 } | |
| 439 } | 444 } |
| 440 } | 445 } |
| 441 if issue != -1 { | 446 if issue != -1 { |
| 442 if rietveld != "" { | 447 if rietveld != "" { |
| 443 rietveld = strings.TrimRight(rietveld, "/") | 448 rietveld = strings.TrimRight(rietveld, "/") |
| 444 ss.Changelist = &resp.Link{ | 449 ss.Changelist = &resp.Link{ |
| 445 Label: fmt.Sprintf("Issue %d", issue), | 450 Label: fmt.Sprintf("Issue %d", issue), |
| 446 URL: fmt.Sprintf("%s/%d", rietveld, issue), | 451 URL: fmt.Sprintf("%s/%d", rietveld, issue), |
| 447 } | 452 } |
| 448 } else { | 453 } else { |
| 449 logging.Warningf(c, "Found issue but not rietveld proper ty.") | 454 logging.Warningf(c, "Found issue but not rietveld proper ty.") |
| 450 } | 455 } |
| 451 } | 456 } |
| 457 if got_revision != "" { | |
| 458 ss.Revision = &resp.Link{ | |
| 459 Label: got_revision, | |
| 460 } | |
| 461 if repository != "" { | |
| 462 ss.Revision.URL = repository + "/+/" + got_revision | |
| 463 } | |
| 464 } | |
| 452 return ss | 465 return ss |
| 453 } | 466 } |
| 454 | 467 |
| 455 func getDebugBuild(c context.Context, builder string, buildNum int) (*buildbotBu ild, error) { | 468 func getDebugBuild(c context.Context, builder string, buildNum int) (*buildbotBu ild, error) { |
| 456 fname := fmt.Sprintf("%s.%d.json", builder, buildNum) | 469 fname := fmt.Sprintf("%s.%d.json", builder, buildNum) |
| 457 // ../buildbot below assumes that | 470 // ../buildbot below assumes that |
| 458 // - this code is not executed by tests outside of this dir | 471 // - this code is not executed by tests outside of this dir |
| 459 // - this dir is a sibling of frontend dir | 472 // - this dir is a sibling of frontend dir |
| 460 path := filepath.Join("..", "buildbot", "testdata", fname) | 473 path := filepath.Join("..", "buildbot", "testdata", fname) |
| 461 raw, err := ioutil.ReadFile(path) | 474 raw, err := ioutil.ReadFile(path) |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 var newAliases map[string][]*buildbotLinkAlias | 643 var newAliases map[string][]*buildbotLinkAlias |
| 631 if l := remainingAliases.Len(); l > 0 { | 644 if l := remainingAliases.Len(); l > 0 { |
| 632 newAliases = make(map[string][]*buildbotLinkAlias, l) | 645 newAliases = make(map[string][]*buildbotLinkAlias, l) |
| 633 remainingAliases.Iter(func(v string) bool { | 646 remainingAliases.Iter(func(v string) bool { |
| 634 newAliases[v] = s.Aliases[v] | 647 newAliases[v] = s.Aliases[v] |
| 635 return true | 648 return true |
| 636 }) | 649 }) |
| 637 } | 650 } |
| 638 s.Aliases = newAliases | 651 s.Aliases = newAliases |
| 639 } | 652 } |
| OLD | NEW |