Skip to content

Commit 0507681

Browse files
authored
Merge pull request #39 from orangekame3/add-directoryOnly
Add output option
2 parents 0ce4868 + 414f966 commit 0507681

File tree

8 files changed

+169
-89
lines changed

8 files changed

+169
-89
lines changed

Taskfile.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,8 @@ tasks:
3535
desc: Run MegaLinter
3636
cmds:
3737
- mega-linter-runner --flavor go
38+
39+
fmt:
40+
desc: Format Go code
41+
cmds:
42+
- go fmt ./...

cmd/root.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ var (
4747
mfa bool
4848
level int
4949
fullPath bool
50+
fileName string
5051
)
5152

5253
var rootCmd = &cobra.Command{
@@ -63,7 +64,11 @@ var rootCmd = &cobra.Command{
6364
MFA: mfa,
6465
}
6566

66-
s3Svc := pkg.InitializeAWSSession(s3Config)
67+
s3Svc, err := pkg.InitializeAWSSession(s3Config)
68+
if err != nil {
69+
log.Fatalf("failed to initialize AWS session: %v", err)
70+
return
71+
}
6772

6873
bucket, prefix, err := extractBucketAndPrefix(args[0])
6974
if err != nil {
@@ -80,19 +85,35 @@ var rootCmd = &cobra.Command{
8085
}
8186

8287
root := gtree.NewRoot(bucket)
83-
if noColor {
88+
if noColor || fileName != "" {
8489
root = pkg.BuildTreeWithoutColor(root, bucket, keys, fullPath)
8590
} else {
8691
root = gtree.NewRoot(color.BlueString(bucket))
8792
root = pkg.BuildTreeWithColor(root, bucket, keys, fullPath)
8893
}
8994

90-
if err := gtree.OutputProgrammably(os.Stdout, root); err != nil {
91-
log.Fatalf("failed to output tree: %v", err)
92-
return
93-
}
9495
fileCount, dirCount := pkg.ProcessKeys(keys)
95-
fmt.Printf("\n%d directories, %d files\n", dirCount, fileCount)
96+
97+
if fileName != "" {
98+
f, err := os.Create(fileName)
99+
if err != nil {
100+
log.Fatalf("failed to create file: %v", err)
101+
return
102+
}
103+
defer f.Close()
104+
if err := gtree.OutputProgrammably(f, root); err != nil {
105+
log.Fatalf("failed to output tree: %v", err)
106+
return
107+
}
108+
fmt.Fprintf(f, "\n%d directories, %d files\n", dirCount, fileCount)
109+
110+
} else {
111+
if err := gtree.OutputProgrammably(os.Stdout, root); err != nil {
112+
log.Fatalf("failed to output tree: %v", err)
113+
return
114+
}
115+
fmt.Printf("\n%d directories, %d files\n", dirCount, fileCount)
116+
}
96117
},
97118
}
98119

@@ -112,7 +133,8 @@ func init() {
112133
rootCmd.Flags().BoolVarP(&noColor, "no-color", "n", false, "Disable colorized output")
113134
rootCmd.Flags().BoolVarP(&mfa, "mfa", "m", false, "Use Multi-Factor Authentication")
114135
rootCmd.Flags().IntVarP(&level, "level", "L", 0, "Descend only level directories")
115-
rootCmd.Flags().BoolVarP(&fullPath, "", "f", false, "Print the full path prefix for each file.")
136+
rootCmd.Flags().BoolVarP(&fullPath, "full-path", "f", false, "Print the full path prefix for each file.")
137+
rootCmd.Flags().StringVarP(&fileName, "output", "o", "", "Send output to filename.")
116138
}
117139

118140
func extractBucketAndPrefix(input string) (string, string, error) {

go.mod

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,31 @@ module github.com/orangekame3/stree
33
go 1.21
44

55
require (
6-
github.com/aws/aws-sdk-go v1.45.6
6+
github.com/aws/aws-sdk-go-v2 v1.30.3
7+
github.com/aws/aws-sdk-go-v2/config v1.27.26
8+
github.com/aws/aws-sdk-go-v2/credentials v1.17.26
9+
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2
710
github.com/ddddddO/gtree v1.9.11
811
github.com/fatih/color v1.15.0
912
github.com/spf13/cobra v1.7.0
1013
)
1114

1215
require (
16+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
17+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
18+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
19+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
20+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
21+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15 // indirect
22+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
23+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17 // indirect
24+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
25+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15 // indirect
26+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 // indirect
27+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
28+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
29+
github.com/aws/smithy-go v1.20.3 // indirect
1330
github.com/inconshreveable/mousetrap v1.1.0 // indirect
14-
github.com/jmespath/go-jmespath v0.4.0 // indirect
1531
github.com/mattn/go-colorable v0.1.13 // indirect
1632
github.com/mattn/go-isatty v0.0.17 // indirect
1733
github.com/pelletier/go-toml/v2 v2.1.0 // indirect

go.sum

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,39 @@
1-
github.com/aws/aws-sdk-go v1.45.6 h1:Y2isQQBZsnO15dzUQo9YQRThtHgrV200XCH05BRHVJI=
2-
github.com/aws/aws-sdk-go v1.45.6/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
1+
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
2+
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
3+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
4+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
5+
github.com/aws/aws-sdk-go-v2/config v1.27.26 h1:T1kAefbKuNum/AbShMsZEro6eRkeOT8YILfE9wyjAYQ=
6+
github.com/aws/aws-sdk-go-v2/config v1.27.26/go.mod h1:ivWHkAWFrw/nxty5Fku7soTIVdqZaZ7dw+tc5iGW3GA=
7+
github.com/aws/aws-sdk-go-v2/credentials v1.17.26 h1:tsm8g/nJxi8+/7XyJJcP2dLrnK/5rkFp6+i2nhmz5fk=
8+
github.com/aws/aws-sdk-go-v2/credentials v1.17.26/go.mod h1:3vAM49zkIa3q8WT6o9Ve5Z0vdByDMwmdScO0zvThTgI=
9+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
10+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
11+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
12+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
13+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
14+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
15+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
16+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
17+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15 h1:Z5r7SycxmSllHYmaAZPpmN8GviDrSGhMS6bldqtXZPw=
18+
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.15/go.mod h1:CetW7bDE00QoGEmPUoZuRog07SGVAUVW6LFpNP0YfIg=
19+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
20+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
21+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17 h1:YPYe6ZmvUfDDDELqEKtAd6bo8zxhkm+XEFEzQisqUIE=
22+
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.17/go.mod h1:oBtcnYua/CgzCWYN7NZ5j7PotFDaFSUjCYVTtfyn7vw=
23+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
24+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
25+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15 h1:246A4lSTXWJw/rmlQI+TT2OcqeDMKBdyjEQrafMaQdA=
26+
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.15/go.mod h1:haVfg3761/WF7YPuJOER2MP0k4UAXyHaLclKXB6usDg=
27+
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2 h1:sZXIzO38GZOU+O0C+INqbH7C2yALwfMWpd64tONS/NE=
28+
github.com/aws/aws-sdk-go-v2/service/s3 v1.58.2/go.mod h1:Lcxzg5rojyVPU/0eFwLtcyTaek/6Mtic5B1gJo7e/zE=
29+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 h1:Fv1vD2L65Jnp5QRsdiM64JvUM4Xe+E0JyVsRQKv6IeA=
30+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
31+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
32+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
33+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
34+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
35+
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
36+
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
337
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
438
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
539
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -10,18 +44,13 @@ github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
1044
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
1145
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
1246
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
13-
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
14-
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
15-
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
16-
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
1747
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
1848
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
1949
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
2050
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
2151
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
2252
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
2353
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
24-
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
2554
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2655
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2756
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -36,46 +65,15 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
3665
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
3766
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
3867
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
39-
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
4068
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
4169
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
42-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
43-
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
44-
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
45-
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
46-
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
47-
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
48-
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
49-
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
50-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
51-
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
5270
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
5371
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
54-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
55-
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
56-
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
57-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
58-
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
5972
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
60-
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
6173
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
6274
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
63-
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
64-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
65-
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
66-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
67-
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
68-
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
69-
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
70-
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
71-
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
72-
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
73-
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
74-
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
7575
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
7676
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
77-
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
78-
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
7977
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
8078
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
8179
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

init/create_dummy_data.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
start_date="2023-01-01"
4+
end_date="2024-07-16"
5+
6+
current_date="$start_date"
7+
8+
while [ "$current_date" != "$(gdate -I -d "$end_date + 1 day")" ]; do
9+
# Convert date to the required format: YYYY/MM/DD
10+
formatted_date=$(gdate -d "$current_date" +"%Y/%m/%d")
11+
12+
# Create the directory structure
13+
mkdir -p "$formatted_date"
14+
15+
# Create the dummy.txt file in the directory
16+
touch "$formatted_date/dummy.txt"
17+
18+
# Move to the next date
19+
current_date=$(gdate -I -d "$current_date + 1 day")
20+
done

pkg/s3.go

Lines changed: 58 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
package pkg
33

44
import (
5+
"context"
56
"strings"
67

7-
"github.com/aws/aws-sdk-go/aws"
8-
"github.com/aws/aws-sdk-go/aws/credentials"
9-
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
10-
"github.com/aws/aws-sdk-go/aws/session"
11-
"github.com/aws/aws-sdk-go/service/s3"
8+
"github.com/aws/aws-sdk-go-v2/aws"
9+
"github.com/aws/aws-sdk-go-v2/config"
10+
"github.com/aws/aws-sdk-go-v2/credentials"
11+
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
12+
"github.com/aws/aws-sdk-go-v2/service/s3"
1213
)
1314

1415
// S3Config represents the configuration for an S3 session
@@ -21,45 +22,56 @@ type S3Config struct {
2122
}
2223

2324
// InitializeAWSSession returns an AWS session based on the provided configuration
24-
func InitializeAWSSession(config S3Config) *s3.S3 {
25-
var sess *session.Session
26-
if config.Local {
27-
sessOptions := session.Options{
28-
Config: aws.Config{
29-
Region: aws.String("us-east-1"),
30-
Endpoint: aws.String("http://localhost:4566"),
31-
S3ForcePathStyle: aws.Bool(true),
32-
Credentials: credentials.NewStaticCredentials("dummy", "dummy", ""),
33-
},
25+
func InitializeAWSSession(conf S3Config) (*s3.Client, error) {
26+
var awsConfig aws.Config
27+
var err error
28+
29+
if conf.Local {
30+
awsConfig, err = config.LoadDefaultConfig(context.TODO(),
31+
config.WithRegion("us-east-1"),
32+
config.WithEndpointResolver(aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) {
33+
return aws.Endpoint{
34+
URL: "http://localhost:4566",
35+
SigningRegion: "us-east-1",
36+
}, nil
37+
})),
38+
config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider("dummy", "dummy", "")),
39+
)
40+
if conf.AwsRegion != "" {
41+
awsConfig.Region = conf.AwsRegion
42+
}
43+
if conf.EndpointURL != "" {
44+
awsConfig.EndpointResolver = aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) {
45+
return aws.Endpoint{
46+
URL: conf.EndpointURL,
47+
SigningRegion: conf.AwsRegion,
48+
}, nil
49+
})
3450
}
35-
// override region and endpoint
36-
if config.AwsRegion != "" {
37-
sessOptions.Config.Region = aws.String(config.AwsRegion)
51+
} else {
52+
loadOptions := []func(*config.LoadOptions) error{
53+
config.WithSharedConfigProfile(conf.AwsProfile),
3854
}
39-
if config.EndpointURL != "" {
40-
sessOptions.Config.Endpoint = aws.String(config.EndpointURL)
55+
if conf.AwsRegion != "" {
56+
loadOptions = append(loadOptions, config.WithRegion(conf.AwsRegion))
4157
}
42-
sess = session.Must(session.NewSessionWithOptions(sessOptions))
43-
return s3.New(sess)
58+
if conf.MFA {
59+
loadOptions = append(loadOptions, config.WithAssumeRoleCredentialOptions(func(options *stscreds.AssumeRoleOptions) {
60+
options.TokenProvider = stscreds.StdinTokenProvider
61+
}))
62+
}
63+
awsConfig, err = config.LoadDefaultConfig(context.TODO(), loadOptions...)
4464
}
4565

46-
sessOptions := session.Options{
47-
Profile: config.AwsProfile,
48-
SharedConfigState: session.SharedConfigEnable,
49-
}
50-
// override region
51-
if config.AwsRegion != "" {
52-
sessOptions.Config.Region = aws.String(config.AwsRegion)
66+
if err != nil {
67+
return nil, err
5368
}
54-
if config.MFA {
55-
sessOptions.AssumeRoleTokenProvider = stscreds.StdinTokenProvider
56-
}
57-
sess = session.Must(session.NewSessionWithOptions(sessOptions))
58-
return s3.New(sess)
69+
70+
return s3.NewFromConfig(awsConfig), nil
5971
}
6072

6173
// FetchS3ObjectKeys returns a slice of keys for all objects in the specified bucket and prefix
62-
func FetchS3ObjectKeys(s3Svc *s3.S3, bucket string, prefix string, maxDepth *int) ([][]string, error) {
74+
func FetchS3ObjectKeys(s3Client *s3.Client, bucket string, prefix string, maxDepth *int) ([][]string, error) {
6375
var delimiter *string
6476
if maxDepth != nil {
6577
delimiter = aws.String("/")
@@ -87,25 +99,30 @@ func FetchS3ObjectKeys(s3Svc *s3.S3, bucket string, prefix string, maxDepth *int
8799
Delimiter: delimiter,
88100
}
89101

90-
pageHandler := func(page *s3.ListObjectsV2Output, lastPage bool) bool {
102+
paginator := s3.NewListObjectsV2Paginator(s3Client, input)
103+
104+
for paginator.HasMorePages() {
105+
page, err := paginator.NextPage(context.TODO())
106+
if err != nil {
107+
return nil, err
108+
}
109+
91110
for _, obj := range page.Contents {
92111
key := strings.Split(*obj.Key, "/")
93112
keys = append(keys, key)
94113
}
114+
95115
if maxDepth != nil {
116+
96117
for _, commonPrefix := range page.CommonPrefixes {
97118
if _, ok := queued[*commonPrefix.Prefix]; ok {
98119
continue
99120
}
100121
queue = append(queue, *commonPrefix.Prefix)
101122
depth = append(depth, currentDepth+1)
123+
queued[*commonPrefix.Prefix] = struct{}{}
102124
}
103125
}
104-
return !lastPage
105-
}
106-
107-
if err := s3Svc.ListObjectsV2Pages(input, pageHandler); err != nil {
108-
return nil, err
109126
}
110127
}
111128
return keys, nil

pkg/tree.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ func createFullPath(bucket string, keys [][]string) [][]string {
1616
}
1717
return keys
1818
}
19+
1920
// BuildTreeWithColor builds a tree with colored nodes
2021
func BuildTreeWithColor(root *gtree.Node, bucket string, keys [][]string, f bool) *gtree.Node {
2122
if f {

test-example.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello, Prefect!

0 commit comments

Comments
 (0)