Change source manifest data structure
Change-Id: Ic1cc981ba15e2961b845233de350fcf5fe8566ae
diff --git a/cmd/jiri/snapshot_test.go b/cmd/jiri/snapshot_test.go
index 5df119f..7ba0606 100644
--- a/cmd/jiri/snapshot_test.go
+++ b/cmd/jiri/snapshot_test.go
@@ -176,10 +176,10 @@
for i := 0; i < numProjects; i++ {
paths = append(paths, localProjectName(i))
}
- revMap := make(map[string]string)
+ revMap := make(map[string][]byte)
for _, path := range paths {
g := git.NewGit(filepath.Join(fake.X.Root, path))
- if rev, err := g.CurrentRevision(); err != nil {
+ if rev, err := g.CurrentRevisionRaw(); err != nil {
t.Fatal(err)
} else {
revMap[path] = rev
@@ -211,22 +211,27 @@
sm := &project.SourceManifest{
Version: project.SourceManifestVersion,
}
- sm.Checkouts = append(sm.Checkouts, project.SourceCheckout{
- LocalPath: "manifest",
- RepoURL: fake.Projects["manifest"],
- SCMType: project.GIT,
- Revision: revMap["manifest"],
- })
- for i := 0; i < numProjects; i++ {
- sc := project.SourceCheckout{
- SCMType: project.GIT,
- LocalPath: localProjectName(i),
- RepoURL: fake.Projects[remoteProjectName(i)],
- Revision: revMap[localProjectName(i)],
- }
- sm.Checkouts = append(sm.Checkouts, sc)
+ sm.Directories = make(map[string]*project.SourceManifest_Directory)
+ sm.Directories["manifest"] = &project.SourceManifest_Directory{
+ GitCheckout: &project.SourceManifest_GitCheckout{
+ RepoUrl: fake.Projects["manifest"],
+ Revision: revMap["manifest"],
+ TrackingRef: "refs/heads/master",
+ },
}
- sm.Checkouts[3].TrackingRef = "refs/heads/test-branch"
+ for i := 0; i < numProjects; i++ {
+ ref := "refs/heads/master"
+ if i == 2 {
+ ref = "refs/heads/test-branch"
+ }
+ sm.Directories[localProjectName(i)] = &project.SourceManifest_Directory{
+ GitCheckout: &project.SourceManifest_GitCheckout{
+ RepoUrl: fake.Projects[remoteProjectName(i)],
+ Revision: revMap[localProjectName(i)],
+ TrackingRef: ref,
+ },
+ }
+ }
want, err := json.MarshalIndent(sm, "", " ")
if err != nil {
diff --git a/git/git.go b/git/git.go
index 4d43d34..7f0693f 100644
--- a/git/git.go
+++ b/git/git.go
@@ -6,6 +6,7 @@
import (
"fmt"
+
git2go "github.com/libgit2/git2go"
)
@@ -19,6 +20,20 @@
}
}
+func (g *Git) CurrentRevisionRaw() ([]byte, error) {
+ repo, err := git2go.OpenRepository(g.rootDir)
+ if err != nil {
+ return nil, err
+ }
+ defer repo.Free()
+ head, err := repo.Head()
+ if err != nil {
+ return nil, err
+ }
+ defer head.Free()
+ return head.Target()[:], nil
+}
+
func (g *Git) CurrentRevision() (string, error) {
repo, err := git2go.OpenRepository(g.rootDir)
if err != nil {
diff --git a/project/source_manifest.go b/project/source_manifest.go
index 69acc75..2515a8d 100644
--- a/project/source_manifest.go
+++ b/project/source_manifest.go
@@ -13,26 +13,67 @@
"sort"
"fuchsia.googlesource.com/jiri"
+ "fuchsia.googlesource.com/jiri/git"
)
-type SCMType int16
-
const (
- GIT = SCMType(0)
- SourceManifestVersion = 1
+ SourceManifestVersion = int32(0)
)
-type SourceCheckout struct {
- SCMType SCMType `json:"scm_type"`
- RepoURL string `json:"repo_url"`
- Revision string `json:"revision"`
- LocalPath string `json:"local_path"`
- TrackingRef string `json:"tracking_ref,omitempty"`
+type SourceManifest_GitCheckout struct {
+ // The canonicalized URL of the original repo that is considered the “source
+ // of truth” for the source code. Ex.
+ // https://chromium.googlesource.com/chromium/tools/build.git
+ // https://github.com/luci/recipes-py
+ RepoUrl string `json:"repo_url,omitempty"`
+
+ // If different from repo_url, this can be the URL of the repo that the source
+ // was actually fetched from (i.e. a mirror). Ex.
+ // https://chromium.googlesource.com/external/github.com/luci/recipes-py
+ //
+ // If this is empty, it's presumed to be equal to repo_url.
+ FetchUrl string `json:"fetch_url,omitempty"`
+
+ // The fully resolved revision (commit hash) of the source. Ex.
+ // 3617b0eea7ec74b8e731a23fed2f4070cbc284c4
+ //
+ // Note that this is the raw revision bytes, not their hex-encoded form.
+ Revision []byte `json:"revision,omitempty"`
+
+ // The ref that the task used to resolve the revision of the source (if any). Ex.
+ // refs/heads/master
+ // refs/changes/04/511804/4
+ //
+ // This should always be a ref on the hosted repo (not any local alias
+ // like 'refs/remotes/...').
+ //
+ // This should always be an absolute ref (i.e. starts with 'refs/'). An
+ // example of a non-absolute ref would be 'master'.
+ TrackingRef string `json:"tracking_ref,omitempty"`
+}
+
+type SourceManifest_Directory struct {
+ GitCheckout *SourceManifest_GitCheckout `json:"git_checkout,omitempty"`
}
type SourceManifest struct {
- Version int `json:"version"`
- Checkouts []SourceCheckout `json:"checkouts"`
+ // Version will increment on backwards-incompatible changes only. Backwards
+ // compatible changes will not alter this version number.
+ //
+ // Currently, the only valid version number is 0.
+ Version int32 `json:"version"`
+
+ // Map of local file system directory path (with forward slashes) to
+ // a Directory message containing one or more deployments.
+ //
+ // The local path is relative to some job-specific root. This should be used
+ // for informational/display/organization purposes, and should not be used as
+ // a global primary key. i.e. if you depend on chromium/src.git being in
+ // a folder called “src”, I will find you and make really angry faces at you
+ // until you change it...(╬ಠ益ಠ). Instead, implementations should consider
+ // indexing by e.g. git repository URL or cipd package name as more better
+ // primary keys.
+ Directories map[string]*SourceManifest_Directory `json:"directories"`
}
func NewSourceManifest(jirix *jiri.X, projects Projects) (*SourceManifest, error) {
@@ -46,21 +87,25 @@
i++
}
sm := &SourceManifest{
- Version: SourceManifestVersion,
- Checkouts: make([]SourceCheckout, len(p)),
+ Version: SourceManifestVersion,
+ Directories: make(map[string]*SourceManifest_Directory),
}
sort.Sort(ProjectsByPath(p))
- for i, proj := range p {
- sc := SourceCheckout{
- SCMType: GIT,
- RepoURL: proj.Remote,
- Revision: proj.Revision,
- LocalPath: proj.Path,
+ for _, proj := range p {
+ gc := &SourceManifest_GitCheckout{
+ RepoUrl: proj.Remote,
}
- if proj.RemoteBranch != "" && proj.RemoteBranch != "master" {
- sc.TrackingRef = "refs/heads/" + proj.RemoteBranch
+ g := git.NewGit(filepath.Join(jirix.Root, proj.Path))
+ if rev, err := g.CurrentRevisionRaw(); err != nil {
+ return nil, err
+ } else {
+ gc.Revision = rev
}
- sm.Checkouts[i] = sc
+ if proj.RemoteBranch == "" {
+ proj.RemoteBranch = "master"
+ }
+ gc.TrackingRef = "refs/heads/" + proj.RemoteBranch
+ sm.Directories[proj.Path] = &SourceManifest_Directory{GitCheckout: gc}
}
return sm, nil
}