blob: 722df5a9c27302fff71c8da0032874d791dab957 [file] [log] [blame] [edit]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package integrationtests
import (
"path/filepath"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"go.fuchsia.dev/jiri/project"
)
func TestSimpleProject(t *testing.T) {
t.Parallel()
remoteDir := t.TempDir()
setupGitRepo(t, remoteDir, map[string]any{
"manifest": project.Manifest{
Projects: []project.Project{
{
Name: "manifest",
Path: "manifest_dir",
Remote: remoteDir,
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "manifest", remoteDir)
jiri("update")
checkDirContents(t, root, []string{
"manifest_dir/manifest",
})
}
func TestUpdateWithDirtyProject(t *testing.T) {
t.Parallel()
remoteDir := t.TempDir()
setupGitRepo(t, remoteDir, map[string]any{
"manifest": project.Manifest{
Projects: []project.Project{
{
Name: "manifest",
Path: "manifest_dir",
Remote: remoteDir,
},
},
},
"foo.txt": "original contents\n",
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "manifest", remoteDir)
jiri("update")
fooPath := filepath.Join(root, "manifest_dir", "foo.txt")
newContents := "new contents\n"
writeFile(t, fooPath, newContents)
// A Jiri update should not discard uncommitted changes.
jiri("update")
got := readFile(t, fooPath)
if diff := cmp.Diff(newContents, got); diff != "" {
t.Errorf("Wrong foo.txt contents after update (-want +got):\n%s", diff)
}
}
func TestImportRemoteManifest(t *testing.T) {
t.Parallel()
// Set up a remote repo containing a manifest that includes the repo itself
// at the root.
bRemoteDir := t.TempDir()
setupGitRepo(t, bRemoteDir, map[string]any{
"b_manifest": project.Manifest{
Projects: []project.Project{
// The project itself.
{
Name: "b",
Remote: bRemoteDir,
Path: ".",
},
},
},
"foo.txt": "foo\n",
})
// Set up a remote repo that imports the above repository at the root of the
// checkout.
aRemoteDir := t.TempDir()
setupGitRepo(t, aRemoteDir, map[string]any{
"a_manifest": project.Manifest{
Imports: []project.Import{
{
Name: "b",
Manifest: "b_manifest",
Remote: bRemoteDir,
Revision: currentRevision(t, bRemoteDir),
Root: "",
},
},
Projects: []project.Project{
{
Name: "a",
Remote: aRemoteDir,
Path: "a",
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "-name", "a", "a_manifest", aRemoteDir)
jiri("update")
checkDirContents(t, root, []string{
"foo.txt",
"b_manifest",
"a/a_manifest",
})
}
func TestSuperprojectChange(t *testing.T) {
t.Parallel()
remoteDir := t.TempDir()
setupGitRepo(t, remoteDir, map[string]any{
"manifest": project.Manifest{
Projects: []project.Project{
{
Name: "manifest",
Path: "manifest_dir",
Remote: remoteDir,
GitSubmodules: true,
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root, "-enable-submodules=yes-please")
jiri("import", "manifest", remoteDir)
jiri("update")
// Commit a new file to the superproject's upstream.
writeFile(t, filepath.Join(remoteDir, "bar.txt"), "bar")
runSubprocess(t, remoteDir, "git", "add", ".")
runSubprocess(t, remoteDir, "git", "commit", "-m", "Add bar.txt")
// Do an update, which should pull in the superproject changes.
jiri("update")
checkDirContents(t, root, []string{
"manifest_dir/bar.txt",
"manifest_dir/manifest",
})
}
// Checks that -local-manifest works.
func TestUpdateWithLocalManifestChange(t *testing.T) {
t.Parallel()
subprojectRemoteDir := t.TempDir()
setupGitRepo(t, subprojectRemoteDir, map[string]any{
"foo.txt": "foo",
})
remoteDir := t.TempDir()
setupGitRepo(t, remoteDir, map[string]any{
"manifest": project.Manifest{
Projects: []project.Project{
{
Name: "manifest",
Path: "manifest_dir",
Remote: remoteDir,
},
{
Name: "subproject",
Path: "subproject",
Remote: subprojectRemoteDir,
Revision: currentRevision(t, subprojectRemoteDir),
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "manifest", remoteDir)
jiri("update")
originalContents := []string{
"manifest_dir/manifest",
"subproject/foo.txt",
}
checkDirContents(t, root, originalContents)
// Advance the subproject to a new revision, with a new file.
writeFile(t, filepath.Join(subprojectRemoteDir, "new_file.txt"), "new file contents")
runSubprocess(t, subprojectRemoteDir, "git", "add", "new_file.txt")
runSubprocess(t, subprojectRemoteDir, "git", "commit", "-m", "Add new_file.txt")
subprojectNewRevision := currentRevision(t, subprojectRemoteDir)
// Edit the manifest to point to the new revision.
localManifestPath := filepath.Join(root, "manifest_dir", "manifest")
jiri("edit", "-project", "subproject="+subprojectNewRevision, localManifestPath)
// A plain old `jiri update` should ignore the manifest changes...
jiri("update")
checkDirContents(t, root, originalContents)
// ... but with the -local-manifest flag, Jiri should respect local manifest
// changes and pull in the locally pinned version of the subproject, with
// the new file.
jiri("update", "-local-manifest")
checkDirContents(t, root, append(originalContents,
"subproject/new_file.txt",
))
}
// Checks that -local-manifest-project <list of projects> respects changes in a manifest in an <import>ed
// project, not just the top-level manifest project.
func TestUpdateWithLocalManifestChangeInImportedProject(t *testing.T) {
t.Parallel()
cRemoteDir := t.TempDir()
setupGitRepo(t, cRemoteDir, map[string]any{
"foo.txt": "foo\n",
})
bRemoteDir := t.TempDir()
setupGitRepo(t, bRemoteDir, map[string]any{
"b_manifest": project.Manifest{
Projects: []project.Project{
{
Name: "b",
Path: ".",
Remote: bRemoteDir,
},
{
Name: "c",
Path: "c",
Remote: cRemoteDir,
Revision: currentRevision(t, cRemoteDir),
},
},
},
})
// Set up a remote repo that imports the above repository at the root of the
// checkout.
remoteDir := t.TempDir()
setupGitRepo(t, remoteDir, map[string]any{
"a_manifest": project.Manifest{
Imports: []project.Import{
{
Name: "b",
Manifest: "b_manifest",
Remote: bRemoteDir,
Revision: currentRevision(t, bRemoteDir),
Root: "",
},
},
Projects: []project.Project{
{
Name: "a",
Remote: remoteDir,
Path: "a",
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "-name", "a", "a_manifest", remoteDir)
jiri("update")
checkDirContents(t, root, []string{
"a/a_manifest",
"b_manifest",
"c/foo.txt",
})
// Create a new commit in the transitive dependency.
writeFile(t, filepath.Join(cRemoteDir, "new_file.txt"), "contents")
runSubprocess(t, cRemoteDir, "git", "add", "new_file.txt")
runSubprocess(t, cRemoteDir, "git", "commit", "-m", "Add new_file.txt")
newTransitiveDepRevision := currentRevision(t, cRemoteDir)
// Edit the local manifest to point to the new revision.
localManifestPath := filepath.Join(root, "b_manifest")
jiri("edit", "-project", "c="+newTransitiveDepRevision, localManifestPath)
jiri("update", "-local-manifest-project", "b")
checkDirContents(t, root, []string{
"a/a_manifest",
"b_manifest",
"c/foo.txt",
"c/new_file.txt",
})
}
// Checks that -local-manifest-project <list of projects> doesn't update a
// project that isn't in the <list of projects> passed to
// -local-manifest-project.
func TestUpdateWithProjectNotListedInLocalManifestProjects(t *testing.T) {
t.Parallel()
cRemoteDir := t.TempDir()
setupGitRepo(t, cRemoteDir, map[string]any{
"foo.txt": "foo\n",
})
bRemoteDir := t.TempDir()
setupGitRepo(t, bRemoteDir, map[string]any{
"b_manifest": project.Manifest{
Projects: []project.Project{
{
Name: "b",
Path: "b",
Remote: bRemoteDir,
},
{
Name: "c",
Path: "c",
Remote: cRemoteDir,
Revision: currentRevision(t, cRemoteDir),
},
},
},
})
// Set up a remote repo that imports the above repository at the root of the
// checkout.
aRemoteDir := t.TempDir()
setupGitRepo(t, aRemoteDir, map[string]any{
"a_manifest": project.Manifest{
Imports: []project.Import{
{
Name: "b",
Manifest: "b_manifest",
Remote: bRemoteDir,
Revision: currentRevision(t, bRemoteDir),
Root: "",
},
},
Projects: []project.Project{
{
Name: "a",
Remote: aRemoteDir,
Path: "a",
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "-name", "a", "a_manifest", aRemoteDir)
jiri("update")
checkDirContents(t, root, []string{
"a/a_manifest",
"b/b_manifest",
"c/foo.txt",
})
// Create a new commit in the transitive dependency.
writeFile(t, filepath.Join(cRemoteDir, "new_file.txt"), "contents")
runSubprocess(t, cRemoteDir, "git", "add", "new_file.txt")
runSubprocess(t, cRemoteDir, "git", "commit", "-m", "Add new_file.txt")
cNewRevision := currentRevision(t, cRemoteDir)
// Edit the local manifest to point to the new revision.
bManifestLocalPath := filepath.Join(root, "b", "b_manifest")
jiri("edit", "-project", "c="+cNewRevision, bManifestLocalPath)
jiri("update", "-local-manifest-project", "b")
// Because -local-manifest-project is not specified, the manifest edit should not
// take effect after this jiri update.
jiri("update")
checkDirContents(t, root, []string{
"a/a_manifest",
"b/b_manifest",
"c/foo.txt",
})
}
// Checks that if bar is an import of foo and `jiri update -local-manifest-project=bar` and `jiri
// update -local-manifest-project=foo local-manifest-project=bar` behave the same way: only bar
// is updated.
func TestUpdateOnlyImport(t *testing.T) {
t.Parallel()
bRemoteDir := t.TempDir()
setupGitRepo(t, bRemoteDir, map[string]any{
"b_manifest": project.Manifest{
Projects: []project.Project{
{
Name: "b",
Path: "b",
Remote: bRemoteDir,
},
},
},
})
// Set up a remote repo that imports the above repository.
aRemoteDir := t.TempDir()
setupGitRepo(t, aRemoteDir, map[string]any{
"a_manifest": project.Manifest{
Imports: []project.Import{
{
Name: "b",
Manifest: "b_manifest",
Remote: bRemoteDir,
Revision: currentRevision(t, bRemoteDir),
Root: "",
},
},
Projects: []project.Project{
{
Name: "a",
Remote: aRemoteDir,
Path: "a",
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "-name", "a", "a_manifest", aRemoteDir)
jiri("update")
aLocalDir := filepath.Join(root, "a")
oldRev := currentRevision(t, aLocalDir)
// Create a new commit in manifest repository's remote.
writeFile(t, filepath.Join(aRemoteDir, "new_file.txt"), "contents")
runSubprocess(t, aRemoteDir, "git", "add", "new_file.txt")
runSubprocess(t, aRemoteDir, "git", "commit", "-m", "Add new_file.txt")
jiri("update", "-local-manifest-project", "b")
log := runSubprocess(t, aLocalDir, "git", "log", "--pretty=oneline")
newRev := currentRevision(t, aLocalDir)
// Validate that the local "a" repo is still at the original commit, not the
// new one.
if newRev != oldRev {
t.Errorf("Root project revision incorrect; want %q, got %q. Git log:\n%s", oldRev, newRev, log)
}
}
// Test that it's possible to change the path of a project to a subdirectory of
// the old path, even if that subdirectory already existed.
func TestMovingProjectIntoSubdir(t *testing.T) {
t.Parallel()
aRemoteDir := t.TempDir()
setupGitRepo(t, aRemoteDir, map[string]any{
// project A contains a "src" subdirectory, which shouldn't stop us from
// moving project A into the "src" subdirectory of its original
// path.
"src/foo.txt": "foo\n",
})
bRemoteDir := t.TempDir()
setupGitRepo(t, bRemoteDir, map[string]any{
"manifest": project.Manifest{
Projects: []project.Project{
{
Name: "a",
Path: "path_to_a",
Remote: aRemoteDir,
},
},
},
})
root := t.TempDir()
jiri := jiriInit(t, root)
jiri("import", "manifest", bRemoteDir)
jiri("update")
checkDirContents(t, root, []string{
"path_to_a/src/foo.txt",
})
manifestPath := filepath.Join(bRemoteDir, "manifest")
manifestContents := readFile(t, manifestPath)
// Update project a's path from `path_to_a` to `path_to_a/src`, which is a
// directory that already exists (but as a subdirectory of project a).
writeFile(t, manifestPath, strings.ReplaceAll(manifestContents, "path_to_a", "path_to_a/src"))
runSubprocess(t, bRemoteDir, "git", "commit", "-am", "Update project a's path")
jiri("update")
checkDirContents(t, root, []string{
"path_to_a/src/src/foo.txt",
})
}