Skip to content

Commit 485748c

Browse files
committed
cmd/swarm: improve uploader output and add defaultpath option
1 parent 080699f commit 485748c

File tree

2 files changed

+68
-22
lines changed

2 files changed

+68
-22
lines changed

cmd/swarm/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ var (
108108
Name: "manifest",
109109
Usage: "Automatic manifest upload",
110110
}
111+
SwarmUploadDefaultPath = cli.StringFlag{
112+
Name: "defaultpath",
113+
Usage: "path to file served for empty url path (none)",
114+
}
111115
)
112116

113117
func init() {
@@ -179,6 +183,7 @@ Prints the swarm hash of file or directory.
179183
SwarmApiFlag,
180184
SwarmRecursiveUploadFlag,
181185
SwarmWantManifestFlag,
186+
SwarmUploadDefaultPath,
182187
}
183188
app.Flags = append(app.Flags, debug.Flags...)
184189
app.Before = func(ctx *cli.Context) error {

cmd/swarm/upload.go

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
"mime"
2828
"net/http"
2929
"os"
30+
"os/user"
31+
"path"
3032
"path/filepath"
3133
"strings"
3234

@@ -39,6 +41,7 @@ func upload(ctx *cli.Context) {
3941
bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
4042
recursive = ctx.GlobalBool(SwarmRecursiveUploadFlag.Name)
4143
wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
44+
defaultPath = ctx.GlobalString(SwarmUploadDefaultPath.Name)
4245
)
4346
if len(args) != 1 {
4447
log.Fatal("need filename as the first and only argument")
@@ -48,63 +51,101 @@ func upload(ctx *cli.Context) {
4851
file = args[0]
4952
client = &client{api: bzzapi}
5053
mroot manifest
54+
entry manifestEntry
5155
)
52-
fi, err := os.Stat(file)
56+
fi, err := os.Stat(expandPath(file))
5357
if err != nil {
5458
log.Fatal(err)
5559
}
5660
if fi.IsDir() {
5761
if !recursive {
5862
log.Fatal("argument is a directory and recursive upload is disabled")
5963
}
60-
mroot, err = client.uploadDirectory(file)
64+
mroot, err = client.uploadDirectory(file, defaultPath)
6165
} else {
62-
mroot, err = client.uploadFile(file, fi)
63-
if wantManifest {
64-
// Wrap the raw file entry in a proper manifest so both hashes get printed.
65-
mroot = manifest{Entries: []manifest{mroot}}
66-
}
66+
entry, err = client.uploadFile(file, fi)
67+
mroot = manifest{[]manifestEntry{entry}}
6768
}
6869
if err != nil {
6970
log.Fatalln("upload failed:", err)
7071
}
71-
if wantManifest {
72-
hash, err := client.uploadManifest(mroot)
73-
if err != nil {
74-
log.Fatalln("manifest upload failed:", err)
72+
if !wantManifest {
73+
// Print the manifest. This is the only output to stdout.
74+
mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
75+
fmt.Println(string(mrootJSON))
76+
return
77+
}
78+
hash, err := client.uploadManifest(mroot)
79+
if err != nil {
80+
log.Fatalln("manifest upload failed:", err)
81+
}
82+
fmt.Println(hash)
83+
}
84+
85+
// Expands a file path
86+
// 1. replace tilde with users home dir
87+
// 2. expands embedded environment variables
88+
// 3. cleans the path, e.g. /a/b/../c -> /a/c
89+
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
90+
func expandPath(p string) string {
91+
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
92+
if home := homeDir(); home != "" {
93+
p = home + p[1:]
7594
}
76-
mroot.Hash = hash
7795
}
96+
return path.Clean(os.ExpandEnv(p))
97+
}
7898

79-
// Print the manifest. This is the only output to stdout.
80-
mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
81-
fmt.Println(string(mrootJSON))
99+
func homeDir() string {
100+
if home := os.Getenv("HOME"); home != "" {
101+
return home
102+
}
103+
if usr, err := user.Current(); err == nil {
104+
return usr.HomeDir
105+
}
106+
return ""
82107
}
83108

84109
// client wraps interaction with the swarm HTTP gateway.
85110
type client struct {
86111
api string
87112
}
88113

114+
// manifest is the JSON representation of a swarm manifest.
115+
type manifestEntry struct {
116+
Hash string `json:"hash,omitempty"`
117+
ContentType string `json:"contentType,omitempty"`
118+
Path string `json:"path,omitempty"`
119+
}
120+
89121
// manifest is the JSON representation of a swarm manifest.
90122
type manifest struct {
91-
Hash string `json:"hash,omitempty"`
92-
ContentType string `json:"contentType,omitempty"`
93-
Path string `json:"path,omitempty"`
94-
Entries []manifest `json:"entries,omitempty"`
123+
Entries []manifestEntry `json:"entries,omitempty"`
95124
}
96125

97-
func (c *client) uploadFile(file string, fi os.FileInfo) (manifest, error) {
126+
func (c *client) uploadFile(file string, fi os.FileInfo) (manifestEntry, error) {
98127
hash, err := c.uploadFileContent(file, fi)
99-
m := manifest{
128+
m := manifestEntry{
100129
Hash: hash,
101130
ContentType: mime.TypeByExtension(filepath.Ext(fi.Name())),
102131
}
103132
return m, err
104133
}
105134

106-
func (c *client) uploadDirectory(dir string) (manifest, error) {
135+
func (c *client) uploadDirectory(dir string, defaultPath string) (manifest, error) {
107136
dirm := manifest{}
137+
if len(defaultPath) > 0 {
138+
fi, err := os.Stat(defaultPath)
139+
if err != nil {
140+
log.Fatal(err)
141+
}
142+
entry, err := c.uploadFile(defaultPath, fi)
143+
if err != nil {
144+
log.Fatal(err)
145+
}
146+
entry.Path = ""
147+
dirm.Entries = append(dirm.Entries, entry)
148+
}
108149
prefix := filepath.ToSlash(filepath.Clean(dir)) + "/"
109150
err := filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
110151
if err != nil || fi.IsDir() {

0 commit comments

Comments
 (0)