@@ -50,8 +50,6 @@ func upload(ctx *cli.Context) {
5050 var (
5151 file = args [0 ]
5252 client = & client {api : bzzapi }
53- mroot manifest
54- entry manifestEntry
5553 )
5654 fi , err := os .Stat (expandPath (file ))
5755 if err != nil {
@@ -61,14 +59,21 @@ func upload(ctx *cli.Context) {
6159 if ! recursive {
6260 log .Fatal ("argument is a directory and recursive upload is disabled" )
6361 }
64- mroot , err = client .uploadDirectory (file , defaultPath )
65- } else {
66- entry , err = client .uploadFile (file , fi )
67- mroot = manifest {[]manifestEntry {entry }}
62+ if ! wantManifest {
63+ log .Fatal ("manifest is required for directory uploads" )
64+ }
65+ mhash , err := client .uploadDirectory (file , defaultPath )
66+ if err != nil {
67+ log .Fatal (err )
68+ }
69+ fmt .Println (mhash )
70+ return
6871 }
72+ entry , err := client .uploadFile (file , fi )
6973 if err != nil {
7074 log .Fatalln ("upload failed:" , err )
7175 }
76+ mroot := manifest {[]manifestEntry {entry }}
7277 if ! wantManifest {
7378 // Print the manifest. This is the only output to stdout.
7479 mrootJSON , _ := json .MarshalIndent (mroot , "" , " " )
@@ -123,43 +128,43 @@ type manifest struct {
123128 Entries []manifestEntry `json:"entries,omitempty"`
124129}
125130
126- func (c * client ) uploadFile (file string , fi os.FileInfo ) (manifestEntry , error ) {
127- hash , err := c .uploadFileContent (file , fi )
128- m := manifestEntry {
129- Hash : hash ,
130- ContentType : mime .TypeByExtension (filepath .Ext (fi .Name ())),
131+ func (c * client ) uploadDirectory (dir string , defaultPath string ) (string , error ) {
132+ mhash , err := c .postRaw ("application/json" , 2 , ioutil .NopCloser (bytes .NewReader ([]byte ("{}" ))))
133+ if err != nil {
134+ return "" , fmt .Errorf ("failed to upload empty manifest" )
131135 }
132- return m , err
133- }
134-
135- func (c * client ) uploadDirectory (dir string , defaultPath string ) (manifest , error ) {
136- dirm := manifest {}
137136 if len (defaultPath ) > 0 {
138137 fi , err := os .Stat (defaultPath )
139138 if err != nil {
140- log . Fatal ( err )
139+ return "" , err
141140 }
142- entry , err : = c .uploadFile ( defaultPath , fi )
141+ mhash , err = c .uploadToManifest ( mhash , "" , defaultPath , fi )
143142 if err != nil {
144- log . Fatal ( err )
143+ return "" , err
145144 }
146- entry .Path = ""
147- dirm .Entries = append (dirm .Entries , entry )
148145 }
149146 prefix := filepath .ToSlash (filepath .Clean (dir )) + "/"
150- err : = filepath .Walk (dir , func (path string , fi os.FileInfo , err error ) error {
147+ err = filepath .Walk (dir , func (path string , fi os.FileInfo , err error ) error {
151148 if err != nil || fi .IsDir () {
152149 return err
153150 }
154151 if ! strings .HasPrefix (path , dir ) {
155152 return fmt .Errorf ("path %s outside directory %s" , path , dir )
156153 }
157- entry , err := c .uploadFile (path , fi )
158- entry .Path = strings .TrimPrefix (filepath .ToSlash (filepath .Clean (path )), prefix )
159- dirm .Entries = append (dirm .Entries , entry )
154+ uripath := strings .TrimPrefix (filepath .ToSlash (filepath .Clean (path )), prefix )
155+ mhash , err = c .uploadToManifest (mhash , uripath , path , fi )
160156 return err
161157 })
162- return dirm , err
158+ return mhash , err
159+ }
160+
161+ func (c * client ) uploadFile (file string , fi os.FileInfo ) (manifestEntry , error ) {
162+ hash , err := c .uploadFileContent (file , fi )
163+ m := manifestEntry {
164+ Hash : hash ,
165+ ContentType : mime .TypeByExtension (filepath .Ext (fi .Name ())),
166+ }
167+ return m , err
163168}
164169
165170func (c * client ) uploadFileContent (file string , fi os.FileInfo ) (string , error ) {
@@ -181,6 +186,31 @@ func (c *client) uploadManifest(m manifest) (string, error) {
181186 return c .postRaw ("application/json" , int64 (len (jsm )), ioutil .NopCloser (bytes .NewReader (jsm )))
182187}
183188
189+ func (c * client ) uploadToManifest (mhash string , path string , fpath string , fi os.FileInfo ) (string , error ) {
190+ fd , err := os .Open (fpath )
191+ if err != nil {
192+ return "" , err
193+ }
194+ defer fd .Close ()
195+ log .Printf ("uploading file %s (%d bytes) and adding path %v" , fpath , fi .Size (), path )
196+ req , err := http .NewRequest ("PUT" , c .api + "/bzz:/" + mhash + "/" + path , fd )
197+ if err != nil {
198+ return "" , err
199+ }
200+ req .Header .Set ("content-type" , mime .TypeByExtension (filepath .Ext (fi .Name ())))
201+ req .ContentLength = fi .Size ()
202+ resp , err := http .DefaultClient .Do (req )
203+ if err != nil {
204+ return "" , err
205+ }
206+ defer resp .Body .Close ()
207+ if resp .StatusCode >= 400 {
208+ return "" , fmt .Errorf ("bad status: %s" , resp .Status )
209+ }
210+ content , err := ioutil .ReadAll (resp .Body )
211+ return string (content ), err
212+ }
213+
184214func (c * client ) postRaw (mimetype string , size int64 , body io.ReadCloser ) (string , error ) {
185215 req , err := http .NewRequest ("POST" , c .api + "/bzzr:/" , body )
186216 if err != nil {
0 commit comments