Skip to content

Commit

Permalink
lakectl local: posix improvements (#8257)
Browse files Browse the repository at this point in the history
* lakectl local: posix improvements

* Fix test

* CR Fixes
  • Loading branch information
N-o-Z authored Oct 2, 2024
1 parent aecc37a commit c939d71
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 7 deletions.
2 changes: 2 additions & 0 deletions cmd/lakectl/cmd/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ func localDiff(ctx context.Context, client apigen.ClientWithResponsesInterface,
changes, err := local.DiffLocalWithHead(currentRemoteState, path, local.Config{
SkipNonRegularFiles: cfg.Local.SkipNonRegularFiles,
IncludePerm: cfg.Experimental.Local.POSIXPerm.Enabled,
IncludeUID: cfg.Experimental.Local.POSIXPerm.IncludeUID,
IncludeGID: cfg.Experimental.Local.POSIXPerm.IncludeGID,
})
if err != nil {
DieErr(err)
Expand Down
2 changes: 2 additions & 0 deletions cmd/lakectl/cmd/local_checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ func localCheckout(cmd *cobra.Command, localPath string, specifiedRef string, co
SyncFlags: syncFlags,
SkipNonRegularFiles: cfg.Local.SkipNonRegularFiles,
IncludePerm: cfg.Experimental.Local.POSIXPerm.Enabled,
IncludeUID: cfg.Experimental.Local.POSIXPerm.IncludeUID,
IncludeGID: cfg.Experimental.Local.POSIXPerm.IncludeGID,
})
// confirm on local changes
if confirmByFlag && len(diffs) > 0 {
Expand Down
2 changes: 2 additions & 0 deletions cmd/lakectl/cmd/local_clone.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ var localCloneCmd = &cobra.Command{
SyncFlags: syncFlags,
SkipNonRegularFiles: cfg.Local.SkipNonRegularFiles,
IncludePerm: cfg.Experimental.Local.POSIXPerm.Enabled,
IncludeUID: cfg.Experimental.Local.POSIXPerm.IncludeUID,
IncludeGID: cfg.Experimental.Local.POSIXPerm.IncludeGID,
})
err = s.Sync(localPath, stableRemote, ch)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions cmd/lakectl/cmd/local_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ var localCommitCmd = &cobra.Command{
SyncFlags: syncFlags,
SkipNonRegularFiles: cfg.Local.SkipNonRegularFiles,
IncludePerm: cfg.Experimental.Local.POSIXPerm.Enabled,
IncludeUID: cfg.Experimental.Local.POSIXPerm.IncludeUID,
IncludeGID: cfg.Experimental.Local.POSIXPerm.IncludeGID,
})
err = s.Sync(idx.LocalPath(), remote, c)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions cmd/lakectl/cmd/local_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ var localPullCmd = &cobra.Command{
SyncFlags: syncFlags,
SkipNonRegularFiles: cfg.Local.SkipNonRegularFiles,
IncludePerm: cfg.Experimental.Local.POSIXPerm.Enabled,
IncludeUID: cfg.Experimental.Local.POSIXPerm.IncludeUID,
IncludeGID: cfg.Experimental.Local.POSIXPerm.IncludeGID,
})
err = s.Sync(idx.LocalPath(), newBase, c)
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion cmd/lakectl/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ type Configuration struct {
Experimental struct {
Local struct {
POSIXPerm struct {
Enabled bool `mapstructure:"enabled"`
Enabled bool `mapstructure:"enabled"`
IncludeUID bool `mapstructure:"include_uid"`
IncludeGID bool `mapstructure:"include_gid"`
} `mapstructure:"posix_permissions"`
} `mapstructure:"local"`
} `mapstructure:"experimental"`
Expand Down
2 changes: 2 additions & 0 deletions pkg/local/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ type Config struct {
SkipNonRegularFiles bool
// IncludePerm - Experimental: preserve Unix file permissions
IncludePerm bool
IncludeUID bool
IncludeGID bool
}
2 changes: 1 addition & 1 deletion pkg/local/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ func DiffLocalWithHead(left <-chan apigen.ObjectStats, rightPath string, cfg Con
// dirs might have different sizes on different operating systems
sizeChanged := !info.IsDir() && localBytes != swag.Int64Value(currentRemoteFile.SizeBytes)
mtimeChanged := localMtime != remoteMtime
permissionsChanged := cfg.IncludePerm && isPermissionsChanged(info, currentRemoteFile)
permissionsChanged := isPermissionsChanged(info, currentRemoteFile, cfg)
if sizeChanged || mtimeChanged || permissionsChanged {
// we made a change!
changes = append(changes, &Change{ChangeSourceLocal, localPath, ChangeTypeModified})
Expand Down
90 changes: 88 additions & 2 deletions pkg/local/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ func TestDiffLocal(t *testing.T) {
cases := []struct {
Name string
IncludeUnixPermissions bool
IncludeGID bool
IncludeUID bool
LocalPath string
InitLocalPath func() string
CleanLocalPath func(localPath string)
Expand Down Expand Up @@ -58,6 +60,8 @@ func TestDiffLocal(t *testing.T) {
{
Name: "t1_no_diff_include_folders",
IncludeUnixPermissions: true,
IncludeGID: true,
IncludeUID: true,
LocalPath: "testdata/localdiff/t1",
RemoteList: []apigen.ObjectStats{
{
Expand Down Expand Up @@ -196,6 +200,8 @@ func TestDiffLocal(t *testing.T) {
{
Name: "t1_folder_added",
IncludeUnixPermissions: true,
IncludeGID: true,
IncludeUID: true,
LocalPath: "testdata/localdiff/t1",
RemoteList: []apigen.ObjectStats{
{
Expand Down Expand Up @@ -238,6 +244,8 @@ func TestDiffLocal(t *testing.T) {
{
Name: "t1_unix_permissions_modified",
IncludeUnixPermissions: true,
IncludeGID: true,
IncludeUID: true,
LocalPath: "testdata/localdiff/t1/sub",
RemoteList: []apigen.ObjectStats{
{
Expand All @@ -249,12 +257,50 @@ func TestDiffLocal(t *testing.T) {
Path: "folder/",
SizeBytes: swag.Int64(1),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid+1, osGid, local.DefaultDirectoryPermissions-umask),
Metadata: getPermissionsMetadata(osUid, osGid+1, local.DefaultDirectoryPermissions-umask),
}, {
Path: "folder/f.txt",
SizeBytes: swag.Int64(6),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid, osGid, local.DefaultFilePermissions-umask),
Metadata: getPermissionsMetadata(osUid+1, osGid, local.DefaultFilePermissions-umask),
},
},
Expected: []*local.Change{
{
Path: "f.txt",
Type: local.ChangeTypeModified,
},
{
Path: "folder/",
Type: local.ChangeTypeModified,
},
{
Path: "folder/f.txt",
Type: local.ChangeTypeModified,
},
},
},
{
Name: "t1_unix_permissions_modified_only_gid",
IncludeUnixPermissions: true,
IncludeGID: true,
LocalPath: "testdata/localdiff/t1/sub",
RemoteList: []apigen.ObjectStats{
{
Path: "f.txt",
SizeBytes: swag.Int64(3),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid, osGid, 755),
}, {
Path: "folder/",
SizeBytes: swag.Int64(1),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid, osGid+1, local.DefaultDirectoryPermissions-umask),
}, {
Path: "folder/f.txt",
SizeBytes: swag.Int64(6),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid+1, osGid, local.DefaultFilePermissions-umask),
},
},
Expected: []*local.Change{
Expand All @@ -268,9 +314,45 @@ func TestDiffLocal(t *testing.T) {
},
},
},
{
Name: "t1_unix_permissions_modified_only_uid",
IncludeUnixPermissions: true,
IncludeUID: true,
LocalPath: "testdata/localdiff/t1/sub",
RemoteList: []apigen.ObjectStats{
{
Path: "f.txt",
SizeBytes: swag.Int64(3),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid, osGid, 755),
}, {
Path: "folder/",
SizeBytes: swag.Int64(1),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid, osGid+1, local.DefaultDirectoryPermissions-umask),
}, {
Path: "folder/f.txt",
SizeBytes: swag.Int64(6),
Mtime: diffTestCorrectTime,
Metadata: getPermissionsMetadata(osUid+1, osGid, local.DefaultFilePermissions-umask),
},
},
Expected: []*local.Change{
{
Path: "f.txt",
Type: local.ChangeTypeModified,
},
{
Path: "folder/f.txt",
Type: local.ChangeTypeModified,
},
},
},
{
Name: "t1_empty_folder_removed",
IncludeUnixPermissions: true,
IncludeGID: true,
IncludeUID: true,
LocalPath: "testdata/localdiff/t1/sub/folder",
RemoteList: []apigen.ObjectStats{
{
Expand Down Expand Up @@ -314,6 +396,8 @@ func TestDiffLocal(t *testing.T) {
{
Name: "empty_folder_added",
IncludeUnixPermissions: true,
IncludeGID: true,
IncludeUID: true,
InitLocalPath: func() string {
return createTempEmptyFolder(t)
},
Expand Down Expand Up @@ -360,6 +444,8 @@ func TestDiffLocal(t *testing.T) {

changes, err := local.DiffLocalWithHead(lc, tt.LocalPath, local.Config{
IncludePerm: tt.IncludeUnixPermissions,
IncludeUID: tt.IncludeUID,
IncludeGID: tt.IncludeGID,
})

if tt.CleanLocalPath != nil {
Expand Down
14 changes: 12 additions & 2 deletions pkg/local/posix_permissions.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ func getPermissionFromFileInfo(info os.FileInfo) (*POSIXPermissions, error) {
return permissionsFromFileInfo(info)
}

func isPermissionsChanged(localFileInfo os.FileInfo, remoteFileStats apigen.ObjectStats) bool {
func isPermissionsChanged(localFileInfo os.FileInfo, remoteFileStats apigen.ObjectStats, cfg Config) bool {
if !cfg.IncludePerm {
return false
}
local, err := getPermissionFromFileInfo(localFileInfo)
if err != nil {
return true
Expand All @@ -94,5 +97,12 @@ func isPermissionsChanged(localFileInfo os.FileInfo, remoteFileStats apigen.Obje
return true
}

return local.Mode != remote.Mode || local.POSIXOwnership != remote.POSIXOwnership
if cfg.IncludeUID && local.UID != remote.UID {
return true
}
if cfg.IncludeGID && local.GID != remote.GID {
return true
}

return local.Mode != remote.Mode
}
10 changes: 9 additions & 1 deletion pkg/local/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,15 @@ func (s *SyncManager) download(ctx context.Context, rootPath string, remote *uri

// change ownership and permissions
if s.cfg.IncludePerm {
if err = os.Chown(destination, perm.UID, perm.GID); err != nil {
uid := perm.UID
gid := perm.GID
if !s.cfg.IncludeUID {
uid = -1
}
if !s.cfg.IncludeGID {
gid = -1
}
if err = os.Chown(destination, uid, gid); err != nil {
return err
}
err = syscall.Chmod(destination, uint32(perm.Mode))
Expand Down

0 comments on commit c939d71

Please sign in to comment.