@@ -27,6 +27,8 @@ import (
27
27
"mime"
28
28
"net/http"
29
29
"os"
30
+ "os/user"
31
+ "path"
30
32
"path/filepath"
31
33
"strings"
32
34
@@ -39,6 +41,7 @@ func upload(ctx *cli.Context) {
39
41
bzzapi = strings .TrimRight (ctx .GlobalString (SwarmApiFlag .Name ), "/" )
40
42
recursive = ctx .GlobalBool (SwarmRecursiveUploadFlag .Name )
41
43
wantManifest = ctx .GlobalBoolT (SwarmWantManifestFlag .Name )
44
+ defaultPath = ctx .GlobalString (SwarmUploadDefaultPath .Name )
42
45
)
43
46
if len (args ) != 1 {
44
47
log .Fatal ("need filename as the first and only argument" )
@@ -48,63 +51,101 @@ func upload(ctx *cli.Context) {
48
51
file = args [0 ]
49
52
client = & client {api : bzzapi }
50
53
mroot manifest
54
+ entry manifestEntry
51
55
)
52
- fi , err := os .Stat (file )
56
+ fi , err := os .Stat (expandPath ( file ) )
53
57
if err != nil {
54
58
log .Fatal (err )
55
59
}
56
60
if fi .IsDir () {
57
61
if ! recursive {
58
62
log .Fatal ("argument is a directory and recursive upload is disabled" )
59
63
}
60
- mroot , err = client .uploadDirectory (file )
64
+ mroot , err = client .uploadDirectory (file , defaultPath )
61
65
} 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 }}
67
68
}
68
69
if err != nil {
69
70
log .Fatalln ("upload failed:" , err )
70
71
}
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 :]
75
94
}
76
- mroot .Hash = hash
77
95
}
96
+ return path .Clean (os .ExpandEnv (p ))
97
+ }
78
98
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 ""
82
107
}
83
108
84
109
// client wraps interaction with the swarm HTTP gateway.
85
110
type client struct {
86
111
api string
87
112
}
88
113
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
+
89
121
// manifest is the JSON representation of a swarm manifest.
90
122
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"`
95
124
}
96
125
97
- func (c * client ) uploadFile (file string , fi os.FileInfo ) (manifest , error ) {
126
+ func (c * client ) uploadFile (file string , fi os.FileInfo ) (manifestEntry , error ) {
98
127
hash , err := c .uploadFileContent (file , fi )
99
- m := manifest {
128
+ m := manifestEntry {
100
129
Hash : hash ,
101
130
ContentType : mime .TypeByExtension (filepath .Ext (fi .Name ())),
102
131
}
103
132
return m , err
104
133
}
105
134
106
- func (c * client ) uploadDirectory (dir string ) (manifest , error ) {
135
+ func (c * client ) uploadDirectory (dir string , defaultPath string ) (manifest , error ) {
107
136
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
+ }
108
149
prefix := filepath .ToSlash (filepath .Clean (dir )) + "/"
109
150
err := filepath .Walk (dir , func (path string , fi os.FileInfo , err error ) error {
110
151
if err != nil || fi .IsDir () {
0 commit comments