-
Notifications
You must be signed in to change notification settings - Fork 54
feat: upgrade existing filesystem #264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
491cd0c
a6e57f7
5da0450
5703751
26bb2b3
4a14230
865c1b8
0343ddc
e116424
5b9d408
7861c8d
27a0d22
5f377b0
f74265c
799373c
dbe3f30
becfe42
3c994b8
6ebb893
ceac217
7e34e32
e1d4e17
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ import ( | |
| "github.com/canonical/chisel/internal/cache" | ||
| "github.com/canonical/chisel/internal/setup" | ||
| "github.com/canonical/chisel/internal/slicer" | ||
| "github.com/canonical/chisel/public/manifest" | ||
| ) | ||
|
|
||
| var shortCutHelp = "Cut a tree with selected slices" | ||
|
|
@@ -73,6 +74,24 @@ func (cmd *cmdCut) Execute(args []string) error { | |
| } | ||
| } | ||
|
|
||
| mfest, err := slicer.SelectValidManifest(cmd.RootDir, release) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if mfest != nil { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like how all this code ended up looking like. It took several iterations but I am quite happy with the result now. |
||
| err = mfest.IterateSlices("", func(slice *manifest.Slice) error { | ||
| sk, err := setup.ParseSliceKey(slice.Name) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| sliceKeys = append(sliceKeys, sk) | ||
| return nil | ||
| }) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } | ||
|
|
||
| selection, err := setup.Select(release, sliceKeys, cmd.Arch) | ||
| if err != nil { | ||
| return err | ||
|
|
@@ -125,6 +144,7 @@ func (cmd *cmdCut) Execute(args []string) error { | |
| Selection: selection, | ||
| Archives: archives, | ||
| TargetDir: cmd.RootDir, | ||
| Manifest: mfest, | ||
| }) | ||
| return err | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,7 +42,7 @@ type Entry struct { | |
| // | ||
| // Create can return errors from the os package. | ||
| func Create(options *CreateOptions) (*Entry, error) { | ||
| o, err := getValidOptions(options) | ||
| o, err := getValidCreateOptions(options) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
@@ -124,7 +124,7 @@ func Create(options *CreateOptions) (*Entry, error) { | |
| // information recorded in Entry. The Hash and Size attributes are set on | ||
| // calling Close() on the Writer. | ||
| func CreateWriter(options *CreateOptions) (io.WriteCloser, *Entry, error) { | ||
| o, err := getValidOptions(options) | ||
| o, err := getValidCreateOptions(options) | ||
| if err != nil { | ||
| return nil, nil, err | ||
| } | ||
|
|
@@ -166,11 +166,22 @@ func createDir(o *CreateOptions) error { | |
| if err != nil { | ||
| return err | ||
| } | ||
| err = os.Mkdir(path, o.Mode) | ||
| if os.IsExist(err) { | ||
| return nil | ||
| fileinfo, err := os.Lstat(path) | ||
| if err == nil { | ||
| if fileinfo.IsDir() { | ||
| if fileinfo.Mode() != o.Mode && o.OverrideMode { | ||
| return os.Chmod(path, o.Mode) | ||
| } | ||
| return nil | ||
| } | ||
| err = os.Remove(path) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| } else if !os.IsNotExist(err) { | ||
| return err | ||
| } | ||
| return err | ||
| return os.Mkdir(path, o.Mode) | ||
|
Comment on lines
+169
to
+184
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A couple of things:
|
||
| } | ||
|
|
||
| func createFile(o *CreateOptions) error { | ||
|
|
@@ -241,7 +252,7 @@ func createHardLink(o *CreateOptions) error { | |
| return err | ||
| } | ||
|
|
||
| func getValidOptions(options *CreateOptions) (*CreateOptions, error) { | ||
| func getValidCreateOptions(options *CreateOptions) (*CreateOptions, error) { | ||
| optsCopy := *options | ||
| o := &optsCopy | ||
| if o.Root == "" { | ||
|
|
@@ -257,7 +268,7 @@ func getValidOptions(options *CreateOptions) (*CreateOptions, error) { | |
| func absPath(root, relPath string) (string, error) { | ||
| path := filepath.Clean(filepath.Join(root, relPath)) | ||
| if !strings.HasPrefix(path, root) { | ||
| return "", fmt.Errorf("cannot create path %s outside of root %s", path, root) | ||
| return "", fmt.Errorf("cannot handle path %s outside of root %s", path, root) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to change the error message? It feels unrelated to the PR. |
||
| } | ||
| return path, nil | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| package fsutil | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "io/fs" | ||
| "os" | ||
| "path/filepath" | ||
| ) | ||
|
|
||
| type MoveOptions struct { | ||
| SrcRoot string | ||
| DstRoot string | ||
| // Path is relative to Root. | ||
| Path string | ||
| Mode fs.FileMode | ||
| // If MakeParents is true, missing parent directories of Path are | ||
| // created with permissions 0755. | ||
| MakeParents bool | ||
| // If OverrideMode is true and entry already exists, update the mode. Does | ||
| // not affect symlinks. | ||
| OverrideMode bool | ||
| } | ||
|
|
||
| // Move moves or create a filesystem entry according to the provided options. | ||
| // | ||
| // Move can return errors from the os package. | ||
| func Move(options *MoveOptions) error { | ||
| o, err := getValidMoveOptions(options) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| srcPath, err := absPath(options.SrcRoot, o.Path) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| dstPath, err := absPath(options.DstRoot, o.Path) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| if o.MakeParents { | ||
| if err := os.MkdirAll(filepath.Dir(dstPath), 0o755); err != nil { | ||
| return err | ||
| } | ||
| } | ||
|
|
||
| switch o.Mode & fs.ModeType { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at the API it feels a bit premature to make it this general where in reality we are creating folders (and calling rmdir) and renaming files. Let's have the discussion and don't do anything yet, but what do you think about inlining it?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So far |
||
| case 0, fs.ModeSymlink: | ||
| err = os.Rename(srcPath, dstPath) | ||
| case fs.ModeDir: | ||
| err = createDir(&CreateOptions{ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not moving the directory, it is left behind. It is also unexpected when an API is called Move and it moves the directory without its contents. |
||
| Root: o.DstRoot, | ||
| Path: o.Path, | ||
| Mode: o.Mode, | ||
| OverrideMode: o.OverrideMode, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should always be true or else we are not moving anything, it shouldn't be an option of Move.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. |
||
| }) | ||
| default: | ||
| err = fmt.Errorf("unsupported file type: %s", o.Path) | ||
| } | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func getValidMoveOptions(options *MoveOptions) (*MoveOptions, error) { | ||
| optsCopy := *options | ||
| o := &optsCopy | ||
| if o.SrcRoot == "" { | ||
| return nil, fmt.Errorf("internal error: MoveOptions.SrcRoot is unset") | ||
| } | ||
| if o.DstRoot == "" { | ||
| return nil, fmt.Errorf("internal error: MoveOptions.DstRoot is unset") | ||
| } | ||
| if o.SrcRoot != "/" { | ||
| o.SrcRoot = filepath.Clean(o.SrcRoot) + "/" | ||
| } | ||
| if o.DstRoot != "/" { | ||
| o.DstRoot = filepath.Clean(o.DstRoot) + "/" | ||
| } | ||
| return o, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general our philosophy is that we should be able to cut a release from main at any point in time. That is, if we ever do a bug fix we should be able to release a point version. This is changing how Chisel works in folders with a manifest and it is not the correct behavior (yet) so I would prefer if we could gate this functionality over a environmental variable or a debug command or any other mechanism.