Skip to content

Commit

Permalink
rework csv renaming implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ayoisaiah committed Aug 31, 2024
1 parent 2ec9c7e commit 8e379c4
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 62 deletions.
34 changes: 14 additions & 20 deletions find/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/ayoisaiah/f2/internal/config"
"github.com/ayoisaiah/f2/internal/file"
"github.com/ayoisaiah/f2/report"
)

// readCSVFile reads all the records contained in a CSV file specified by
Expand Down Expand Up @@ -45,16 +46,18 @@ func handleCSV(conf *config.Config) (file.Changes, error) {
return nil, err
}

findSlice := make([]string, 0, len(records))
replacementSlice := make([]string, 0, len(records))

for _, record := range records {
for i, record := range records {
if len(record) == 0 {
continue
}

source := strings.TrimSpace(record[0])

err := os.Chdir(conf.WorkingDir)
if err != nil {
return nil, err
}

absSourcePath, absErr := filepath.Abs(source)
if absErr != nil {
return nil, absErr
Expand All @@ -64,6 +67,10 @@ func handleCSV(conf *config.Config) (file.Changes, error) {
if statErr != nil {
// Skip missing source files
if errors.Is(statErr, os.ErrNotExist) {
if conf.Verbose {
report.NonExistentFile(fileInfo.Name(), i+1)
}

continue
}
return nil, statErr
Expand All @@ -85,30 +92,17 @@ func handleCSV(conf *config.Config) (file.Changes, error) {
BaseDir: sourceDir,
IsDir: fileInfo.IsDir(),
Source: fileName,
Target: fileName,
OriginalName: fileName,
SourcePath: absSourcePath,
CSVRow: record,
Position: i,
}

changes = append(changes, match)

var target string
if len(record) > 1 {
target = strings.TrimSpace(record[1])
}

findSlice = append(findSlice, fileName)

replacementSlice = append(replacementSlice, target)
}

if len(conf.ReplacementSlice) == 0 && len(conf.FindSlice) == 0 {
conf.FindSlice = findSlice
conf.ReplacementSlice = replacementSlice

err = conf.SetFindStringRegex(0)
if err != nil {
return nil, err
match.Target = strings.TrimSpace(record[1])
}
}

Expand Down
26 changes: 26 additions & 0 deletions find/find_test/find_csv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package find_test

import (
"testing"

"github.com/ayoisaiah/f2/internal/testutil"
)

var csvCases = []testutil.TestCase{
{
Name: "find matches from csv file",
Want: []string{
"LICENSE.txt",
"backup/documents/.hidden_old_resume.txt",
"projects/project1/index.html",
"projects/project2/index.html",
"videos/funny_cats (3).mp4",
},
Args: []string{"--csv", "input.csv"},
},
}

// TestFindCSV tests file matching with CSV files.
func TestFindCSV(t *testing.T) {
findTest(t, csvCases)
}
5 changes: 0 additions & 5 deletions find/find_test/find_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,3 @@ func findTest(t *testing.T, cases []testutil.TestCase) {
func TestFind(t *testing.T) {
findTest(t, testCases)
}

// TestFindCSV tests file matching with CSV files.
func TestFindCSV(_ *testing.T) {
// TODO: Implement tests once CSV implementation has been revised
}
2 changes: 1 addition & 1 deletion find/find_test/find_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ var windowsTestCases = []testutil.TestCase{

// TestFindWindows only tests search behaviors perculiar to Windows
func TestFindWindows(t *testing.T) {
findTest(t, windowsTestCases)
findTest(t, windowsTestCases, false)
}
7 changes: 7 additions & 0 deletions find/find_test/testdata/input.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Filename,Replacement,Random
LICENSE.txt,LICENCE,GPLv3
backup/documents/.hidden_old_resume.txt,not_hidden.txt,
projects/project1/index.html,main.html,
projects/project2/index.html,{csv.3},profile-page
documents/cv.docx,resume.docx,myname
videos/funny_cats (3).mp4,{%03d},
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/jinzhu/copier v0.4.0
github.com/mattn/go-isatty v0.0.20
github.com/olekukonko/tablewriter v0.0.5
github.com/otiai10/copy v1.14.0
github.com/sebdah/goldie/v2 v2.5.3
github.com/stretchr/testify v1.8.4
github.com/veqryn/slog-context v0.7.0
Expand All @@ -44,6 +45,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down Expand Up @@ -106,6 +110,8 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
19 changes: 15 additions & 4 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ func (c *Config) setOptions(ctx *cli.Context) error {
c.Debug = ctx.Bool("debug")
c.FilesAndDirPaths = ctx.Args().Slice()

if c.CSVFilename != "" {
absPath, err := filepath.Abs(filepath.Dir(c.CSVFilename))
if err != nil {
return err
}

c.WorkingDir = absPath
}

if len(ctx.Args().Slice()) > 0 {
c.FilesAndDirPaths = ctx.Args().Slice()
}
Expand Down Expand Up @@ -291,10 +300,12 @@ func Init(ctx *cli.Context) (*Config, error) {
return nil, err
}

// Get the current working directory
conf.WorkingDir, err = filepath.Abs(".")
if err != nil {
return nil, err
if conf.WorkingDir == "" {
// Get the current working directory
conf.WorkingDir, err = filepath.Abs(".")
if err != nil {
return nil, err
}
}

conf.BackupFilename = generateBackupFilename(conf.WorkingDir)
Expand Down
2 changes: 1 addition & 1 deletion internal/file/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (c Changes) RenderTable(w io.Writer) {
}

d := []string{change.SourcePath, change.TargetPath, changeStatus}
data[change.Position] = d
data[i] = d
}

printTable(data, w)
Expand Down
3 changes: 3 additions & 0 deletions internal/testutil/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/ayoisaiah/f2/app"
"github.com/ayoisaiah/f2/internal/config"
"github.com/ayoisaiah/f2/internal/file"
cp "github.com/otiai10/copy"
)

// TestCase represents a unique test case.
Expand Down Expand Up @@ -44,6 +45,8 @@ func SetupFileSystem(
tb.Fatal(err)
}

_ = cp.Copy("testdata", testDir)

tb.Cleanup(func() {
err = os.RemoveAll(testDir)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
APP := "f2"

test:
@go test ./... --json -coverprofile=coverage.out -coverpkg . | gotestfmt -hide 'empty-packages'
@go test ./... --json -coverprofile=coverage.out -coverpkg=. | gotestfmt -hide 'empty-packages'

[no-cd]
test-pkg filter='.*':
@go test --json -coverprofile=coverage.out -coverpkg=../ -run={{filter}} | gotestfmt
@go test ./... --json -coverprofile=coverage.out -coverpkg=. -run={{filter}} | gotestfmt

[no-cd]
update-golden filter='.*':
@go test --update --json -run={{filter}} | gotestfmt
@go test --update --json -run={{filter}} | gotestfmt

build:
@go build -o bin/{{APP}} ./cmd...
Expand Down
80 changes: 52 additions & 28 deletions replace/replace.go
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,40 @@ func replaceString(conf *config.Config, originalName string) string {
)
}

// applyReplacements applies the configured replacement patterns to the source
// filename
func applyReplacement(
conf *config.Config,
vars *variables,
change *file.Change,
) error {
originalName := change.Source
fileExt := filepath.Ext(originalName)

if conf.IgnoreExt && !change.IsDir {
originalName = pathutil.StripExtension(originalName)
}

change.Target = replaceString(conf, originalName)

// Replace any variables present with their corresponding values
err := replaceVariables(conf, change, vars)
if err != nil {
return err
}

// Reattach the original extension to the new file name
if conf.IgnoreExt && !change.IsDir {
change.Target += fileExt
}

change.Target = strings.TrimSpace(filepath.Clean(change.Target))
change.Status = status.OK
change.TargetPath = filepath.Join(change.BaseDir, change.Target)

return nil
}

// replaceMatches handles the replacement of matches in each file with the
// replacement string.
func replaceMatches(
Expand All @@ -646,39 +680,12 @@ func replaceMatches(
for i := range matches {
change := matches[i]

// FIXME: Produces wrong result when a sort is provided
if len(change.CSVRow) > 0 && i != conf.Search.Index {
if change.Target == "" {
matches[i].Target = change.Source
}

continue
}

change.Position = i
originalName := change.Source
fileExt := filepath.Ext(originalName)

if conf.IgnoreExt && !change.IsDir {
originalName = pathutil.StripExtension(originalName)
}

change.Target = replaceString(conf, originalName)

// Replace any variables present with their corresponding values
err = replaceVariables(conf, change, &vars)
err := applyReplacement(conf, &vars, change)
if err != nil {
return nil, err
}

// Reattach the original extension to the new file name
if conf.IgnoreExt && !change.IsDir {
change.Target += fileExt
}

change.Target = strings.TrimSpace(filepath.Clean(change.Target))
change.Status = status.OK
change.TargetPath = filepath.Join(change.BaseDir, change.Target)
matches[i] = change
}

Expand Down Expand Up @@ -733,6 +740,23 @@ func Replace(
) (file.Changes, error) {
var err error

if conf.CSVFilename != "" {
for i := range changes {
ch := changes[i]

conf.Replacement = ch.Target
vars, err := extractVariables(conf.Replacement)
if err != nil {
return nil, err
}

err = applyReplacement(conf, &vars, ch)
if err != nil {
return nil, err
}
}
}

changes, err = handleReplacementChain(conf, changes)
if err != nil {
return nil, err
Expand Down
11 changes: 11 additions & 0 deletions report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ func BackupFileRemovalFailed(err error) {
)
}

func NonExistentFile(name string, row int) {
pterm.Fprintln(
config.Stderr,
pterm.Sprintf(
"skipping non existent source file at row %d: %s",
row,
name,
),
)
}

// NoMatches prints out a message indicating that the find string failed
// to match any files.
func NoMatches(conf *config.Config) {
Expand Down

0 comments on commit 8e379c4

Please sign in to comment.