Skip to content

Commit d4dfb16

Browse files
authored
Merge pull request #51 from nao1215/import-from-file
Add --input option to import subcommand
2 parents ea41886 + 3eef5ed commit d4dfb16

File tree

11 files changed

+184
-96
lines changed

11 files changed

+184
-96
lines changed

README.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,24 @@ You use the export/import subcommand if you want to install the same golang bi
110110
according to the contents of gup.conf.
111111

112112
```
113-
Environmet A (e.g. ubuntu)
113+
Environments A (e.g. ubuntu)
114114
$ gup export
115115
gup:INFO: Export /home/nao/.config/gup/gup.conf
116116
117-
Environmet B (e.g. debian)
117+
Environments B (e.g. debian)
118118
$ ls /home/nao/.config/gup/gup.conf
119119
/home/nao/.config/gup/gup.conf
120120
$ gup import
121121
```
122+
123+
Alternatively, export subcommand print package information (it's same as gup.conf) that you want to export at STDOUT if you use --output option. import subcommand can also specify the gup.conf file path if you use --input option.
124+
```
125+
※ Environments A (e.g. ubuntu)
126+
$ gup export --output > gup.conf
127+
128+
※ Environments B (e.g. debian)
129+
$ gup import --input=gup.conf
130+
```
122131

123132
### Auto-generate shell completion file (for bash, zsh, fish)
124133
gup command automatically generates shell completion files for bash, zsh, and fish. After the user executes gup, if the shell completion file does not exist in the system, the auto-generation process will begin. To activate the completion feature, restart the shell.

cmd/export.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func export(cmd *cobra.Command, args []string) int {
3939

4040
output, err := cmd.Flags().GetBool("output")
4141
if err != nil {
42-
print.Err(fmt.Errorf("%s: %w", "can not parse command line argument", err))
42+
print.Err(fmt.Errorf("%s: %w", "can not parse command line argument (--output)", err))
4343
return 1
4444
}
4545

cmd/export_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func Test_export_parse_error(t *testing.T) {
271271
got := strings.Split(buf.String(), "\n")
272272

273273
want := []string{
274-
"gup:ERROR: can not parse command line argument: flag accessed but not defined: output",
274+
"gup:ERROR: can not parse command line argument (--output): flag accessed but not defined: output",
275275
"",
276276
}
277277
if diff := cmp.Diff(want, got); diff != "" {

cmd/import.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -26,32 +26,39 @@ Finally, you execute the export subcommand in this state.`,
2626

2727
func init() {
2828
importCmd.Flags().BoolP("dry-run", "n", false, "perform the trial update with no changes")
29+
importCmd.Flags().StringP("input", "i", config.FilePath(), "specify gup.conf file path to import")
2930
rootCmd.AddCommand(importCmd)
3031
}
3132

3233
func runImport(cmd *cobra.Command, args []string) int {
3334
dryRun, err := cmd.Flags().GetBool("dry-run")
3435
if err != nil {
35-
print.Err(fmt.Errorf("%s: %w", "can not parse command line argument", err))
36+
print.Err(fmt.Errorf("%s: %w", "can not parse command line argument (--dry-run)", err))
3637
return 1
3738
}
3839

39-
if !file.IsFile(config.FilePath()) {
40-
print.Err(fmt.Errorf("%s is not found", config.FilePath()))
40+
confFile, err := cmd.Flags().GetString("input")
41+
if err != nil {
42+
print.Err(fmt.Errorf("%s: %w", "can not parse command line argument (--input)", err))
43+
return 1
44+
}
45+
46+
if !file.IsFile(confFile) {
47+
print.Err(fmt.Errorf("%s is not found", confFile))
4148
return 1
4249
}
4350

44-
pkgs, err := config.ReadConfFile()
51+
pkgs, err := config.ReadConfFile(confFile)
4552
if err != nil {
4653
print.Err(err)
4754
return 1
4855
}
4956

5057
if len(pkgs) == 0 {
51-
print.Err("unable to update package: no package information")
58+
print.Err("unable to import package: no package information")
5259
return 1
5360
}
5461

55-
print.Info("start update based on " + config.FilePath())
62+
print.Info("start update based on " + confFile)
5663
return update(pkgs, dryRun)
5764
}

cmd/import_test.go

+46-34
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,92 @@
11
package cmd
22

33
import (
4+
"bytes"
5+
"io"
46
"os"
5-
"path/filepath"
7+
"strings"
68
"testing"
79

10+
"github.com/google/go-cmp/cmp"
11+
"github.com/nao1215/gup/internal/config"
12+
"github.com/nao1215/gup/internal/print"
813
"github.com/spf13/cobra"
914
)
1015

11-
func Test_runImport(t *testing.T) {
16+
func Test_runImport_Error(t *testing.T) {
1217
type args struct {
1318
cmd *cobra.Command
1419
args []string
1520
}
1621
tests := []struct {
17-
name string
18-
args args
19-
home string
20-
want int
22+
name string
23+
args args
24+
home string
25+
want int
26+
stderr []string
2127
}{
2228
{
23-
name: "not exist config file",
24-
args: args{
25-
cmd: &cobra.Command{},
26-
args: []string{},
27-
},
28-
home: "/",
29-
want: 1,
30-
},
31-
{
32-
name: "argument parse error",
29+
name: "argument parse error (--dry-run)",
3330
args: args{
3431
cmd: &cobra.Command{},
3532
args: []string{},
3633
},
3734
home: "",
3835
want: 1,
39-
},
40-
{
41-
name: "config file is empty",
42-
args: args{
43-
cmd: &cobra.Command{},
44-
args: []string{},
36+
stderr: []string{
37+
"gup:ERROR: can not parse command line argument (--dry-run): flag accessed but not defined: dry-run",
38+
"",
4539
},
46-
home: filepath.Join("testdata", "empty_conf"),
47-
want: 1,
4840
},
4941
{
50-
name: "can not read config",
42+
name: "argument parse error (--input)",
5143
args: args{
5244
cmd: &cobra.Command{},
5345
args: []string{},
5446
},
55-
home: filepath.Join("testdata", "can_not_read_conf"),
47+
home: "",
5648
want: 1,
49+
stderr: []string{
50+
"gup:ERROR: can not parse command line argument (--input): flag accessed but not defined: input",
51+
"",
52+
},
5753
},
5854
}
5955
for _, tt := range tests {
6056
t.Run(tt.name, func(t *testing.T) {
61-
if tt.name != "argument parse error" {
57+
if tt.name == "argument parse error (--dry-run)" {
58+
tt.args.cmd.Flags().StringP("input", "i", config.FilePath(), "specify gup.conf file path to import")
59+
} else if tt.name == "argument parse error (--input)" {
6260
tt.args.cmd.Flags().BoolP("dry-run", "n", false, "perform the trial update with no changes")
6361
}
6462

65-
oldHome := os.Getenv("HOME")
66-
if err := os.Setenv("HOME", tt.home); err != nil {
63+
orgStdout := print.Stdout
64+
orgStderr := print.Stderr
65+
pr, pw, err := os.Pipe()
66+
if err != nil {
6767
t.Fatal(err)
6868
}
69-
defer func() {
70-
if err := os.Setenv("HOME", oldHome); err != nil {
71-
t.Fatal(err)
72-
}
73-
}()
69+
print.Stdout = pw
70+
print.Stderr = pw
7471

7572
if got := runImport(tt.args.cmd, tt.args.args); got != tt.want {
7673
t.Errorf("runImport() = %v, want %v", got, tt.want)
7774
}
75+
pw.Close()
76+
print.Stdout = orgStdout
77+
print.Stderr = orgStderr
78+
79+
buf := bytes.Buffer{}
80+
_, err = io.Copy(&buf, pr)
81+
if err != nil {
82+
t.Error(err)
83+
}
84+
defer pr.Close()
85+
got := strings.Split(buf.String(), "\n")
86+
87+
if diff := cmp.Diff(tt.stderr, got); diff != "" {
88+
t.Errorf("value is mismatch (-want +got):\n%s", diff)
89+
}
7890
})
7991
}
8092
}

cmd/root_test.go

+99-42
Original file line numberDiff line numberDiff line change
@@ -489,46 +489,32 @@ func TestExecute_Export_WithOutputOption(t *testing.T) {
489489
}
490490
}
491491

492-
func TestExecute_Import(t *testing.T) {
492+
func TestExecute_Import_WithInputOption(t *testing.T) {
493493
OsExit = func(code int) {}
494494
defer func() {
495495
OsExit = os.Exit
496496
}()
497497

498-
oldHome := os.Getenv("HOME")
499-
if err := os.Setenv("HOME", "testdata"); err != nil {
500-
t.Fatal(err)
501-
}
502-
defer func() {
503-
if err := os.Setenv("HOME", oldHome); err != nil {
504-
t.Fatal(err)
505-
}
506-
}()
507-
508498
gobin, err := goutil.GoBin()
509499
if err != nil {
510500
t.Fatal(err)
511501
}
512-
if file.IsFile(filepath.Join(gobin, "posixer")) {
513-
if err := os.Rename(filepath.Join(gobin, "posixer"), filepath.Join(gobin, "posixer")+".backup"); err != nil {
502+
if file.IsDir(gobin) {
503+
if err := os.Rename(gobin, gobin+".backup"); err != nil {
514504
t.Fatal(err)
515505
}
516506
defer func() {
517-
if err := os.Rename(filepath.Join(gobin, "posixer")+".backup", filepath.Join(gobin, "posixer")); err != nil {
518-
t.Fatal(err)
507+
if file.IsDir(gobin + ".backup") {
508+
os.RemoveAll(gobin)
509+
if err := os.Rename(gobin+".backup", gobin); err != nil {
510+
t.Fatal(err)
511+
}
519512
}
520513
}()
521-
}
522514

523-
if file.IsFile(filepath.Join(gobin, "posixer")) {
524-
if err := os.Rename(filepath.Join(gobin, "posixer"), filepath.Join(gobin, "posixer")+".backup"); err != nil {
515+
if err := os.MkdirAll(gobin, 0755); err != nil {
525516
t.Fatal(err)
526517
}
527-
defer func() {
528-
if err := os.Rename(filepath.Join(gobin, "posixer")+".backup", filepath.Join(gobin, "posixer")); err != nil {
529-
t.Fatal(err)
530-
}
531-
}()
532518
}
533519

534520
defer func() {
@@ -541,33 +527,104 @@ func TestExecute_Import(t *testing.T) {
541527
os.RemoveAll(filepath.Join("testdata", ".cache"))
542528
}()
543529

544-
os.Args = []string{"gup", "import"}
530+
orgStdout := print.Stdout
531+
orgStderr := print.Stderr
532+
pr, pw, err := os.Pipe()
533+
if err != nil {
534+
t.Fatal(err)
535+
}
536+
print.Stdout = pw
537+
print.Stderr = pw
538+
539+
confFile := "testdata/gup_config/nix.conf"
540+
if runtime.GOOS == "windows" {
541+
confFile = "testdata/gup_config/windows.conf"
542+
}
543+
os.Args = []string{"gup", "import", "-i", confFile}
545544
Execute()
546545

547-
if runtime.GOOS != "windows" {
548-
if !file.IsFile(filepath.Join("testdata", ".zsh", "completion", "_gup")) {
549-
t.Errorf("not install " + filepath.Join("testdata", ".zsh", "completion", "_gup"))
550-
}
546+
pw.Close()
547+
print.Stdout = orgStdout
548+
print.Stderr = orgStderr
551549

552-
if !file.IsFile(filepath.Join("testdata", ".config", "fish", "completions", "gup.fish")) {
553-
t.Errorf("not install " + filepath.Join("testdata", ".config", "fish", "completions", "gup.fish"))
554-
}
550+
buf := bytes.Buffer{}
551+
_, err = io.Copy(&buf, pr)
552+
if err != nil {
553+
t.Error(err)
554+
}
555+
defer pr.Close()
556+
got := strings.Split(buf.String(), "\n")
555557

556-
if !file.IsFile(filepath.Join("testdata", ".bash_completion")) {
557-
t.Errorf("not install " + filepath.Join("testdata", ".bash_completion"))
558+
contain := false
559+
for _, v := range got {
560+
if strings.Contains(v, "gup:INFO : [1/1] github.com/nao1215/gup") {
561+
contain = true
558562
}
563+
}
559564

560-
if !file.IsFile("testdata/.zshrc") {
561-
t.Errorf("not install .bash_completion")
562-
}
565+
if !contain {
566+
t.Error("failed import")
567+
}
568+
}
563569

564-
if !file.IsFile(filepath.Join("testdata", ".config", "gup", "assets", "information.png")) {
565-
t.Errorf("not install " + filepath.Join("testdata", ".config", "gup", "assets", "information.png"))
566-
}
570+
func TestExecute_Import_WithBadInputFile(t *testing.T) {
571+
tests := []struct {
572+
name string
573+
inputFile string
574+
want []string
575+
}{
576+
{
577+
name: "specify not exist file",
578+
inputFile: "not_exist_file_path",
579+
want: []string{
580+
"gup:ERROR: not_exist_file_path is not found",
581+
"",
582+
},
583+
},
584+
{
585+
name: "specify empty file",
586+
inputFile: "testdata/gup_config/empty.conf",
587+
want: []string{
588+
"gup:ERROR: unable to import package: no package information",
589+
"",
590+
},
591+
},
592+
}
593+
for _, tt := range tests {
594+
t.Run(tt.name, func(t *testing.T) {
595+
OsExit = func(code int) {}
596+
defer func() {
597+
OsExit = os.Exit
598+
}()
599+
600+
orgStdout := print.Stdout
601+
orgStderr := print.Stderr
602+
pr, pw, err := os.Pipe()
603+
if err != nil {
604+
t.Fatal(err)
605+
}
606+
print.Stdout = pw
607+
print.Stderr = pw
567608

568-
if !file.IsFile(filepath.Join("testdata", ".config", "gup", "assets", "warning.png")) {
569-
t.Errorf("not install " + filepath.Join("testdata", ".config", "gup", "assets", "warning.png"))
570-
}
609+
os.Args = []string{"gup", "import", "-i", tt.inputFile}
610+
Execute()
611+
612+
pw.Close()
613+
print.Stdout = orgStdout
614+
print.Stderr = orgStderr
615+
616+
buf := bytes.Buffer{}
617+
_, err = io.Copy(&buf, pr)
618+
if err != nil {
619+
t.Error(err)
620+
}
621+
defer pr.Close()
622+
got := strings.Split(buf.String(), "\n")
623+
624+
if diff := cmp.Diff(tt.want, got); diff != "" {
625+
t.Errorf("value is mismatch (-want +got):\n%s", diff)
626+
}
627+
})
571628
}
572629
}
573630

cmd/testdata/gup_config/empty.conf

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)