mirror of https://github.com/perkeep/perkeep.git
Merge branch 'master' of danga.com:camlistore
This commit is contained in:
commit
d1eb213ec0
|
@ -21,12 +21,14 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var flagVerbose *bool = flag.Bool("verbose", false, "be verbose")
|
||||
|
||||
var flagCheck *bool = flag.Bool("check", false, "just check for the existence of listed blobs; returning 0 if all our present")
|
||||
var flagOutput *string = flag.String("o", "-", "Output file/directory to create. Use -f to overwrite.")
|
||||
var flagVia *string = flag.String("via", "", "Fetch the blob via the given comma-separated sharerefs (dev only).")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
@ -41,20 +43,40 @@ func main() {
|
|||
|
||||
for n := 0; n < flag.NArg(); n++ {
|
||||
arg := flag.Arg(n)
|
||||
blobref := blobref.Parse(arg)
|
||||
if blobref == nil {
|
||||
br := blobref.Parse(arg)
|
||||
if br == nil {
|
||||
log.Exitf("Failed to parse argument \"%s\" as a blobref.", arg)
|
||||
}
|
||||
if *flagVerbose {
|
||||
log.Printf("Need to fetch %s", blobref.String())
|
||||
log.Printf("Need to fetch %s", br.String())
|
||||
}
|
||||
var (
|
||||
r blobref.ReadSeekCloser
|
||||
err os.Error
|
||||
)
|
||||
|
||||
if len(*flagVia) > 0 {
|
||||
vs := strings.Split(*flagVia, ",", -1)
|
||||
abr := make([]*blobref.BlobRef, len(vs))
|
||||
for i, sbr := range vs {
|
||||
abr[i] = blobref.Parse(sbr)
|
||||
if abr[i] == nil {
|
||||
log.Exitf("Invalid -via blobref: %q", sbr)
|
||||
}
|
||||
if *flagVerbose {
|
||||
log.Printf("via: %s", sbr)
|
||||
}
|
||||
}
|
||||
r, _, err = client.FetchVia(br, abr)
|
||||
} else {
|
||||
r, _, err = client.Fetch(br)
|
||||
}
|
||||
r, _, err := client.Fetch(blobref)
|
||||
if err != nil {
|
||||
log.Exitf("Failed to fetch %q: %s", blobref, err)
|
||||
log.Exitf("Failed to fetch %q: %s", br, err)
|
||||
}
|
||||
_, err = io.Copy(w, r)
|
||||
if err != nil {
|
||||
log.Exitf("Failed transferring %q: %s", blobref, err)
|
||||
log.Exitf("Failed transferring %q: %s", br, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,9 @@ import (
|
|||
var flagBlob = flag.Bool("blob", false, "upload a file's bytes as a single blob")
|
||||
var flagFile = flag.Bool("file", false, "upload a file's bytes as a blob, as well as its JSON file record")
|
||||
var flagPermanode = flag.Bool("permanode", false, "create a new permanode")
|
||||
var flagInit = flag.Bool("init", false, "First-time configuration.")
|
||||
var flagInit = flag.Bool("init", false, "first-time configuration.")
|
||||
var flagShare = flag.Bool("share", false, "create a camli share by haveref with the given blobrefs")
|
||||
var flagTransitive = flag.Bool("transitive", true, "share the transitive closure of the given blobrefs")
|
||||
|
||||
var flagVerbose = flag.Bool("verbose", false, "be verbose")
|
||||
|
||||
|
@ -171,6 +173,17 @@ func (up *Uploader) UploadNewPermanode() (*client.PutResult, os.Error) {
|
|||
return up.Upload(client.NewUploadHandleFromString(signed))
|
||||
}
|
||||
|
||||
func (up *Uploader) UploadShare(target *blobref.BlobRef, transitive bool) (*client.PutResult, os.Error) {
|
||||
unsigned := schema.NewShareRef(schema.ShareHaveRef, target, transitive)
|
||||
|
||||
signed, err := up.SignMap(unsigned)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return up.Upload(client.NewUploadHandleFromString(signed))
|
||||
}
|
||||
|
||||
func sumSet(flags ...*bool) (count int) {
|
||||
for _, f := range flags {
|
||||
if *f {
|
||||
|
@ -190,6 +203,7 @@ Usage: camput
|
|||
camput --init # first time configuration
|
||||
camput --blob <filename(s) to upload as blobs>
|
||||
camput --file <filename(s) to upload as blobs + JSON metadata>
|
||||
camput --share <blobref to share via haveref> [--transitive]
|
||||
`)
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
|
@ -211,7 +225,7 @@ func handleResult(what string, pr *client.PutResult, err os.Error) {
|
|||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if sumSet(flagFile, flagBlob, flagPermanode, flagInit) != 1 {
|
||||
if sumSet(flagFile, flagBlob, flagPermanode, flagInit, flagShare) != 1 {
|
||||
// TODO: say which ones are conflicting
|
||||
usage("Conflicting mode options.")
|
||||
}
|
||||
|
@ -242,6 +256,16 @@ func main() {
|
|||
handleResult("file", pr, err)
|
||||
}
|
||||
}
|
||||
case *flagShare:
|
||||
if flag.NArg() != 1 {
|
||||
log.Exitf("--share only supports one blobref")
|
||||
}
|
||||
br := blobref.Parse(flag.Arg(0))
|
||||
if br == nil {
|
||||
log.Exitf("BlobRef is invalid: %q", flag.Arg(0))
|
||||
}
|
||||
pr, err := uploader.UploadShare(br, *flagTransitive)
|
||||
handleResult("share", pr, err)
|
||||
}
|
||||
|
||||
if *flagVerbose {
|
||||
|
|
|
@ -64,6 +64,10 @@ func (c *Client) Stats() Stats {
|
|||
return c.stats // copy
|
||||
}
|
||||
|
||||
func (c *Client) HasAuthCredentials() bool {
|
||||
return c.password != ""
|
||||
}
|
||||
|
||||
func (c *Client) authHeader() string {
|
||||
return "Basic " + encodeBase64("username:" + c.password)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"camli/blobref"
|
||||
"camli/http"
|
||||
"fmt"
|
||||
|
@ -10,10 +11,29 @@ import (
|
|||
)
|
||||
|
||||
func (c *Client) Fetch(b *blobref.BlobRef) (blobref.ReadSeekCloser, int64, os.Error) {
|
||||
return c.FetchVia(b, nil)
|
||||
}
|
||||
|
||||
func (c *Client) FetchVia(b *blobref.BlobRef, v []*blobref.BlobRef) (blobref.ReadSeekCloser, int64, os.Error) {
|
||||
url := fmt.Sprintf("%s/camli/%s", c.server, b)
|
||||
|
||||
if len(v) > 0 {
|
||||
buf := bytes.NewBufferString(url)
|
||||
buf.WriteString("?via=")
|
||||
for i, br := range v {
|
||||
if i != 0 {
|
||||
buf.WriteString(",")
|
||||
}
|
||||
buf.WriteString(br.String())
|
||||
}
|
||||
url = buf.String()
|
||||
}
|
||||
|
||||
req := http.NewGetRequest(url)
|
||||
req.Header["Authorization"] = c.authHeader()
|
||||
|
||||
if c.HasAuthCredentials() {
|
||||
req.Header["Authorization"] = c.authHeader()
|
||||
}
|
||||
resp, err := req.Send()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
|
@ -24,7 +44,7 @@ func (c *Client) Fetch(b *blobref.BlobRef) (blobref.ReadSeekCloser, int64, os.Er
|
|||
size, _ = strconv.Atoi64(s)
|
||||
}
|
||||
|
||||
return nopSeeker{resp.Body}, size, nil
|
||||
return nopSeeker{resp.Body}, size, nil
|
||||
}
|
||||
|
||||
type nopSeeker struct {
|
||||
|
|
|
@ -203,6 +203,18 @@ func PopulateDirectoryMap(m map[string]interface{}, staticSetRef *blobref.BlobRe
|
|||
m["entries"] = staticSetRef.String()
|
||||
}
|
||||
|
||||
func NewShareRef(authType string, target *blobref.BlobRef, transitive bool) map[string]interface{} {
|
||||
m := newCamliMap(1, "" /* no type yet */)
|
||||
m["camliType"] = "share"
|
||||
m["authType"] = authType
|
||||
m["target"] = target.String()
|
||||
m["transitive"] = transitive
|
||||
return m
|
||||
}
|
||||
|
||||
// Types of ShareRefs
|
||||
const ShareHaveRef = "haveref"
|
||||
|
||||
func rfc3339FromNanos(epochnanos int64) string {
|
||||
nanos := epochnanos % 1e9
|
||||
esec := epochnanos / 1e9
|
||||
|
|
|
@ -12,10 +12,12 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"http"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var flagStorageRoot *string = flag.String("root", "/tmp/camliroot", "Root directory to store files")
|
||||
var flagRequestLog *bool = flag.Bool("reqlog", false, "Log incoming requests")
|
||||
var stealthMode *bool = flag.Bool("stealth", true, "Run in stealth mode.")
|
||||
|
||||
var blobFetcher blobref.Fetcher
|
||||
|
@ -26,6 +28,9 @@ func handleCamli(conn http.ResponseWriter, req *http.Request) {
|
|||
fmt.Sprintf("Unsupported path (%s) or method (%s).",
|
||||
req.URL.Path, req.Method))
|
||||
}
|
||||
if *flagRequestLog {
|
||||
log.Printf("%s %s", req.Method, req.RawURL)
|
||||
}
|
||||
switch req.Method {
|
||||
case "GET":
|
||||
switch req.URL.Path {
|
||||
|
|
Loading…
Reference in New Issue