Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions pkg/util/customcheckpointmanager/customcheckpointmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,15 +296,26 @@ func (cm *customCheckpointManager) CreateCheckpoint(checkpointName string, check
func (cm *customCheckpointManager) isCheckpointUpToDate() (bool, error) {
currentCheckpointFilePath := filepath.Join(cm.currStateDir, cm.checkpointName)

// Current checkpoint is not up to date as it does not exist
if !general.IsPathExists(currentCheckpointFilePath) {
// Current checkpoint is not up to date if it does not exist or if is not a regular file.
currFileExists, err := general.IsRegularFileExists(currentCheckpointFilePath, true)
if err != nil {
return false, fmt.Errorf("[%v] failed to check if current file exists: %w", cm.pluginName, err)
}

if !currFileExists {
return false, nil
}

previousCheckpointFilePath := filepath.Join(cm.prevStateDir, cm.checkpointName)

// When there is no previous checkpoint, we consider the current checkpoint is up to date
if !general.IsPathExists(previousCheckpointFilePath) {
// When there is no previous checkpoint, we consider the current checkpoint is up to date.
// Previous checkpoint does not exist if it is not a regular file.
prevFileExists, err := general.IsRegularFileExists(previousCheckpointFilePath, true)
if err != nil {
return false, fmt.Errorf("[%v] failed to check if previous file exists: %w", cm.pluginName, err)
}

if !prevFileExists {
return true, nil
}

Expand Down
39 changes: 39 additions & 0 deletions pkg/util/general/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,45 @@ func IsPathExists(path string) bool {
return true
}

// IsRegularFileExists is to check whether a regular file specified by the path exists.
// If there is an entry that is not a regular file, make the entry hidden if makeHidden equals true
func IsRegularFileExists(path string, makeHidden bool) (bool, error) {
pathExists := IsPathExists(path)
if pathExists {
// Path exists, check if the file is a regular file
fileInfo, err := os.Stat(path)
if err != nil {
return false, fmt.Errorf("failed to get file info: %w", err)
}

isRegular := fileInfo.Mode().IsRegular()
if !isRegular && makeHidden {
err = makeEntryHidden(path)
if err != nil {
return false, fmt.Errorf("failed to remove directory %s: %w", path, err)
}
}

return isRegular, nil
}

return false, nil
}

// makeEntryHidden makes a file entry hidden by adding a prefix dot
func makeEntryHidden(path string) error {
dir := filepath.Dir(path)
base := filepath.Base(path)

// premature return if the entry is already hidden
if len(base) > 0 && base[0] == '.' {
return nil
}

hiddenPath := filepath.Join(dir, "."+base)
return os.Rename(path, hiddenPath)
}

// ReadFileIntoLines read contents from the given file, and parse them into string slice;
// each string indicates a line in the file
func ReadFileIntoLines(filepath string) ([]string, error) {
Expand Down
146 changes: 146 additions & 0 deletions pkg/util/general/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,3 +747,149 @@ func TestIsFileUpToDate(t *testing.T) {
})
}
}

func TestIsRegularFileExists(t *testing.T) {
t.Parallel()

tmpDir := t.TempDir()

type testCase struct {
name string
setup func(baseDir string) string
makeHidden bool
wantExists bool
expectOriginalExists bool
expectHiddenExists bool
}

makeHiddenPath := func(p string) string {
dir := filepath.Dir(p)
base := filepath.Base(p)
return filepath.Join(dir, "."+base)
}

tests := []testCase{
{
name: "non-existent path without hiding",
setup: func(baseDir string) string { return filepath.Join(baseDir, "not_exists.txt") },
makeHidden: false,
wantExists: false,
expectOriginalExists: false,
expectHiddenExists: false,
},
{
name: "non-existent path with hiding",
setup: func(baseDir string) string { return filepath.Join(baseDir, "not_exists_2.txt") },
makeHidden: true,
wantExists: false,
expectOriginalExists: false,
expectHiddenExists: false,
},
{
name: "regular file exists, no hiding",
setup: func(baseDir string) string {
p := filepath.Join(baseDir, "regular.txt")
assert.NoError(t, os.WriteFile(p, []byte("hello"), 0o644))
return p
},
makeHidden: false,
wantExists: true,
expectOriginalExists: true,
expectHiddenExists: false,
},
{
name: "regular file exists, hiding requested",
setup: func(baseDir string) string {
p := filepath.Join(baseDir, "regular2.txt")
assert.NoError(t, os.WriteFile(p, []byte("hello2"), 0o644))
return p
},
makeHidden: true,
wantExists: true,
expectOriginalExists: true,
expectHiddenExists: false,
},
{
name: "directory exists, no hiding",
setup: func(baseDir string) string {
p := filepath.Join(baseDir, "adir")
assert.NoError(t, os.MkdirAll(p, 0o755))
return p
},
makeHidden: false,
wantExists: false,
expectOriginalExists: true,
expectHiddenExists: false,
},
{
name: "directory exists, hiding requested",
setup: func(baseDir string) string {
p := filepath.Join(baseDir, "bdir")
assert.NoError(t, os.MkdirAll(p, 0o755))
return p
},
makeHidden: true,
wantExists: false,
expectOriginalExists: false,
expectHiddenExists: true,
},
{
name: "symlink to regular file, hiding requested",
setup: func(baseDir string) string {
target := filepath.Join(baseDir, "target_regular.txt")
assert.NoError(t, os.WriteFile(target, []byte("data"), 0o644))
link := filepath.Join(baseDir, "link_to_regular")
assert.NoError(t, os.Symlink(target, link))
return link
},
makeHidden: true,
wantExists: true,
expectOriginalExists: true,
expectHiddenExists: false,
},
{
name: "symlink to directory, hiding requested",
setup: func(baseDir string) string {
target := filepath.Join(baseDir, "target_dir")
assert.NoError(t, os.MkdirAll(target, 0o755))
link := filepath.Join(baseDir, "link_to_dir")
assert.NoError(t, os.Symlink(target, link))
return link
},
makeHidden: true,
wantExists: false,
expectOriginalExists: false,
expectHiddenExists: true,
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

p := tt.setup(tmpDir)

exists, err := IsRegularFileExists(p, tt.makeHidden)
assert.NoError(t, err)
assert.Equal(t, tt.wantExists, exists)

// verify rename behavior
hidden := makeHiddenPath(p)
_, origErr := os.Stat(p)
_, hiddenErr := os.Stat(hidden)

if tt.expectOriginalExists {
assert.NoError(t, origErr)
} else {
assert.True(t, os.IsNotExist(origErr))
}

if tt.expectHiddenExists {
assert.NoError(t, hiddenErr)
} else {
assert.True(t, os.IsNotExist(hiddenErr))
}
})
}
}
Loading