Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Unified Diff: cipd/client/cipd/local/deployer.go

Issue 2657293005: [cipd] Add subdir support to deployer. (Closed)
Patch Set: fix tests Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cipd/client/cipd/client_test.go ('k') | cipd/client/cipd/local/deployer_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cipd/client/cipd/local/deployer.go
diff --git a/cipd/client/cipd/local/deployer.go b/cipd/client/cipd/local/deployer.go
index 1d0e4097eee1884a8af752c939ce534bfade99b4..dd0cbb35be8f8094a488b4b9a45a7893c529e65c 100644
--- a/cipd/client/cipd/local/deployer.go
+++ b/cipd/client/cipd/local/deployer.go
@@ -31,7 +31,8 @@ import (
// File system layout of a site directory <base> for "symlink" install method:
// <base>/.cipd/pkgs/
-// <package name digest>/
+// <arbitrary index>/
+// description.json
// _current -> symlink to fea3ab83440e9dfb813785e16d4101f331ed44f4
// fea3ab83440e9dfb813785e16d4101f331ed44f4/
// bin/
@@ -42,17 +43,17 @@ import (
// tool -> symlink to ../.cipd/pkgs/<package name digest>/_current/bin/tool
// ...
//
-// Where <package name digest> is derived from a package name. It doesn't have
-// to be reversible though, since the package name is still stored in the
-// installed package manifest and can be read from there.
+// Where <arbitrary index> is chosen to be the smallest number available for
+// this installation (installing more packages gets higher numbers, removing
+// packages and installing new ones will reuse the smallest ones).
//
// Some efforts are made to make sure that during the deployment a window of
// inconsistency in the file system is as small as possible.
//
// For "copy" install method everything is much simpler: files are directly
// copied to the site root directory and .cipd/pkgs/* contains only metadata,
-// such as manifest file with a list of extracted files (to know what to
-// uninstall).
+// such as description and manifest files with a list of extracted files (to
+// know what to uninstall).
// Deployer knows how to unzip and place packages into site root directory.
type Deployer interface {
@@ -142,18 +143,18 @@ type deployerImpl struct {
}
func (d *deployerImpl) DeployInstance(ctx context.Context, subdir string, inst PackageInstance) (common.Pin, error) {
- if subdir != "" {
- return common.Pin{}, common.ErrSubdirsNotYetSupported
+ if err := common.ValidateSubdir(subdir); err != nil {
+ return common.Pin{}, err
}
pin := inst.Pin()
- logging.Infof(ctx, "Deploying %s into %s", pin, d.fs.Root())
+ logging.Infof(ctx, "Deploying %s into %s(/%s)", pin, d.fs.Root(), subdir)
// Be paranoid.
if err := common.ValidatePin(pin); err != nil {
return common.Pin{}, err
}
- if _, err := d.fs.EnsureDirectory(ctx, d.fs.Root()); err != nil {
+ if _, err := d.fs.EnsureDirectory(ctx, filepath.Join(d.fs.Root(), subdir)); err != nil {
return common.Pin{}, err
}
@@ -189,7 +190,7 @@ func (d *deployerImpl) DeployInstance(ctx context.Context, subdir string, inst P
}
// Install all new files to the site root.
- err = d.addToSiteRoot(ctx, newManifest.Files, newManifest.InstallMode, pkgPath, destPath)
+ err = d.addToSiteRoot(ctx, subdir, newManifest.Files, newManifest.InstallMode, pkgPath, destPath)
if err != nil {
d.fs.EnsureDirectoryGone(ctx, destPath)
return common.Pin{}, err
@@ -231,7 +232,7 @@ func (d *deployerImpl) DeployInstance(ctx context.Context, subdir string, inst P
toKill = append(toKill, f)
}
}
- d.removeFromSiteRoot(ctx, toKill)
+ d.removeFromSiteRoot(ctx, subdir, toKill)
}()
}
@@ -249,8 +250,8 @@ func (d *deployerImpl) DeployInstance(ctx context.Context, subdir string, inst P
}
func (d *deployerImpl) CheckDeployed(ctx context.Context, subdir, pkg string) (common.Pin, error) {
- if subdir != "" {
- return common.Pin{}, common.ErrSubdirsNotYetSupported
+ if err := common.ValidateSubdir(subdir); err != nil {
+ return common.Pin{}, err
}
pkgPath, err := d.packagePath(ctx, subdir, pkg, false)
@@ -285,8 +286,7 @@ func (d *deployerImpl) FindDeployed(ctx context.Context) (common.PinSliceBySubdi
return nil, err
}
- found := map[string]common.Pin{}
- keys := []string{}
+ found := common.PinMapBySubdir{}
for _, info := range infos {
if !info.IsDir() {
continue
@@ -304,30 +304,23 @@ func (d *deployerImpl) FindDeployed(ctx context.Context) (common.PinSliceBySubdi
// Ignore duplicate entries, they can appear if someone messes with pkgs/*
// structure manually.
- if _, ok := found[desc.PackageName]; !ok {
- keys = append(keys, desc.PackageName)
- found[desc.PackageName] = common.Pin{
- PackageName: desc.PackageName,
- InstanceID: currentID,
+ if _, ok := found[desc.Subdir][desc.PackageName]; !ok {
+ if _, ok := found[desc.Subdir]; !ok {
+ found[desc.Subdir] = common.PinMap{}
}
+ found[desc.Subdir][desc.PackageName] = currentID
}
}
- // Sort by package name.
- sort.Strings(keys)
- out := make(common.PinSlice, len(found))
- for i, k := range keys {
- out[i] = found[k]
- }
- return common.PinSliceBySubdir{"": out}, nil
+ return found.ToSlice(), nil
}
func (d *deployerImpl) RemoveDeployed(ctx context.Context, subdir, packageName string) error {
- if subdir != "" {
- return common.ErrSubdirsNotYetSupported
+ if err := common.ValidateSubdir(subdir); err != nil {
+ return err
}
- logging.Infof(ctx, "Removing %s from %s", packageName, d.fs.Root())
+ logging.Infof(ctx, "Removing %s from %s(/%s)", packageName, d.fs.Root(), subdir)
if err := common.ValidatePackageName(packageName); err != nil {
return err
}
@@ -352,7 +345,7 @@ func (d *deployerImpl) RemoveDeployed(ctx context.Context, subdir, packageName s
if err != nil {
logging.Warningf(ctx, "Package %s is in a broken state: %s", packageName, err)
} else {
- d.removeFromSiteRoot(ctx, manifest.Files)
+ d.removeFromSiteRoot(ctx, subdir, manifest.Files)
}
return d.fs.EnsureDirectoryGone(ctx, pkgPath)
}
@@ -417,11 +410,15 @@ func (s *numSet) smallestNewNum() int {
// If no suitable path is found and allocate is true, this will create a new
// directory with an accompanying description.json. Otherwise this returns "".
func (d *deployerImpl) packagePath(ctx context.Context, subdir, pkg string, allocate bool) (string, error) {
+ if err := common.ValidateSubdir(subdir); err != nil {
+ return "", err
+ }
+
if err := common.ValidatePackageName(pkg); err != nil {
return "", err
}
- rel := filepath.Join(filepath.FromSlash(packagesDir))
+ rel := filepath.FromSlash(packagesDir)
abs, err := d.fs.RootRelToAbs(rel)
if err != nil {
logging.Errorf(ctx, "Can't get absolute path of %q: %s", rel, err)
@@ -447,7 +444,7 @@ func (d *deployerImpl) packagePath(ctx context.Context, subdir, pkg string, allo
logging.Warningf(ctx, "Skipping %q: %s", fullPkgPath, err)
continue
}
- if description.PackageName == pkg {
+ if description.PackageName == pkg && description.Subdir == subdir {
return fullPkgPath, nil
}
}
@@ -462,7 +459,15 @@ func (d *deployerImpl) packagePath(ctx context.Context, subdir, pkg string, allo
return "", err
}
- tmpDir, err := d.TempDir(ctx, strings.Replace(pkg, "/", "_", -1))
+ // take the last 2 components from the pkg path.
+ pkgParts := strings.Split(pkg, "/")
+ prefix := ""
+ if len(pkgParts) > 2 {
+ prefix = strings.Join(pkgParts[len(pkgParts)-2:], "_")
+ } else {
+ prefix = strings.Join(pkgParts, "_")
+ }
+ tmpDir, err := d.TempDir(ctx, prefix)
if err != nil {
logging.Errorf(ctx, "Cannot create new pkg tempdir: %s", err)
return "", err
@@ -510,7 +515,7 @@ func (d *deployerImpl) packagePath(ctx context.Context, subdir, pkg string, allo
logging.Warningf(ctx, "Skipping %q: %s", pkgPath, err)
continue
}
- if description.PackageName == pkg {
+ if description.PackageName == pkg && description.Subdir == subdir {
return pkgPath, nil
}
}
@@ -645,7 +650,7 @@ func (d *deployerImpl) readManifest(ctx context.Context, instanceDir string) (Ma
// addToSiteRoot moves or symlinks files into the site root directory (depending
// on passed installMode).
-func (d *deployerImpl) addToSiteRoot(ctx context.Context, files []FileInfo, installMode InstallMode, pkgDir, srcDir string) error {
+func (d *deployerImpl) addToSiteRoot(ctx context.Context, subdir string, files []FileInfo, installMode InstallMode, pkgDir, srcDir string) error {
// On Windows only InstallModeCopy is supported.
if runtime.GOOS == "windows" {
installMode = InstallModeCopy
@@ -657,17 +662,19 @@ func (d *deployerImpl) addToSiteRoot(ctx context.Context, files []FileInfo, inst
}
for _, f := range files {
- // E.g. bin/tool.
+ // e.g. bin/tool
relPath := filepath.FromSlash(f.Name)
- destAbs, err := d.fs.RootRelToAbs(relPath)
+ // e.g. <base>/<subdir>/bin/tool
+ destAbs, err := d.fs.RootRelToAbs(filepath.Join(subdir, relPath))
if err != nil {
logging.Warningf(ctx, "Invalid relative path %q: %s", relPath, err)
return err
}
if installMode == InstallModeSymlink {
- // E.g. <base>/.cipd/pkgs/name/_current/bin/tool.
+ // e.g. <base>/.cipd/pkgs/name/_current/bin/tool
targetAbs := filepath.Join(pkgDir, currentSymlink, relPath)
- // E.g. ../.cipd/pkgs/name/_current/bin/tool.
+ // e.g. ../.cipd/pkgs/name/_current/bin/tool
+ // has more `../` depending on subdir
targetRel, err := filepath.Rel(filepath.Dir(destAbs), targetAbs)
if err != nil {
logging.Warningf(
@@ -691,7 +698,7 @@ func (d *deployerImpl) addToSiteRoot(ctx context.Context, files []FileInfo, inst
return fmt.Errorf("impossible state")
}
}
- // Best effort cleanup of empty directories after all files has been moved.
+ // Best effort cleanup of empty directories after all files have been moved.
if installMode == InstallModeCopy {
d.removeEmptyDirs(ctx, srcDir)
}
@@ -701,9 +708,9 @@ func (d *deployerImpl) addToSiteRoot(ctx context.Context, files []FileInfo, inst
// removeFromSiteRoot deletes files from the site root directory.
//
// Best effort. Logs errors and carries on.
-func (d *deployerImpl) removeFromSiteRoot(ctx context.Context, files []FileInfo) {
+func (d *deployerImpl) removeFromSiteRoot(ctx context.Context, subdir string, files []FileInfo) {
for _, f := range files {
- absPath, err := d.fs.RootRelToAbs(filepath.FromSlash(f.Name))
+ absPath, err := d.fs.RootRelToAbs(filepath.Join(subdir, filepath.FromSlash(f.Name)))
if err != nil {
logging.Warningf(ctx, "Refusing to remove %q: %s", f.Name, err)
continue
« no previous file with comments | « cipd/client/cipd/client_test.go ('k') | cipd/client/cipd/local/deployer_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698