mirror of https://github.com/perkeep/perkeep.git
cmd: rename camput to pk-put, and make "pk put" call it
A new "put" mode is added to the pk command, so that the "pk put" command can be used to create and upload blobs. What this command does is actually just call the previously named "camput" executable, which is renamed to "pk-put" in this change. This involves adding a new way to register a mode in cmdmain, when such a mode is just meant to call an external binary. To emphasize the distinction, the existing func (to register a sub-command, or a mode) is renamed from RegisterCommand to RegisterMode, and RegisterCommand is now the name of the new func/way. Updates #981 Updates #1056 Change-Id: Ief954c17aa88a376f551df7de4b4e9fe41ad96d1
This commit is contained in:
parent
a13abdeb8c
commit
ce4658abfc
|
@ -44,7 +44,7 @@ type gceCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("gce", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("gce", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(gceCmd)
|
||||
flags.StringVar(&cmd.project, "project", "", "Name of Project.")
|
||||
flags.StringVar(&cmd.zone, "zone", gce.DefaultRegion, "GCE zone or region. If a region is given, a random zone in that region is selected. See https://cloud.google.com/compute/docs/zones")
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Hacks for running camput as a child process on Android.
|
||||
// Hacks for running pk-put as a child process on Android.
|
||||
|
||||
package main
|
||||
|
|
@ -31,7 +31,7 @@ type attrCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("attr", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("attr", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(attrCmd)
|
||||
flags.BoolVar(&cmd.add, "add", false, `Adds attribute (e.g. "tag")`)
|
||||
flags.BoolVar(&cmd.del, "del", false, "Deletes named attribute [value]")
|
||||
|
@ -44,7 +44,7 @@ func (c *attrCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *attrCmd) Usage() {
|
||||
cmdmain.Errorf("Usage: camput [globalopts] attr [attroption] <permanode> <name> <value>")
|
||||
cmdmain.Errorf("Usage: pk-put [globalopts] attr [attroption] <permanode> <name> <value>")
|
||||
}
|
||||
|
||||
func (c *attrCmd) Examples() []string {
|
|
@ -44,7 +44,7 @@ type blobCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("blob", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("blob", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(blobCmd)
|
||||
flags.BoolVar(&cmd.makePermanode, "permanode", false, "Create and associate a new permanode for the blob.")
|
||||
flags.StringVar(&cmd.title, "title", "", "Optional title attribute to set on permanode when using -permanode.")
|
||||
|
@ -59,7 +59,7 @@ func (c *blobCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *blobCmd) Usage() {
|
||||
fmt.Fprintf(cmdmain.Stderr, "Usage: camput [globalopts] blob <files>\n camput [globalopts] blob -\n")
|
||||
fmt.Fprintf(cmdmain.Stderr, "Usage: pk-put [globalopts] blob <files>\n pk-put [globalopts] blob -\n")
|
||||
}
|
||||
|
||||
func (c *blobCmd) Examples() []string {
|
|
@ -93,7 +93,7 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
// So multiple cmd/camput TestFoo funcs run, each with
|
||||
// So multiple cmd/pk-put TestFoo funcs run, each with
|
||||
// an fresh (and not previously closed) Uploader:
|
||||
uploader = nil
|
||||
uploaderOnce = sync.Once{}
|
|
@ -30,7 +30,7 @@ import (
|
|||
"perkeep.org/pkg/cmdmain"
|
||||
)
|
||||
|
||||
// env is the environment that a camput test runs within.
|
||||
// env is the environment that a pk-put test runs within.
|
||||
type env struct {
|
||||
// stdin is the standard input, or /dev/null if nil
|
||||
stdin io.Reader
|
||||
|
@ -88,7 +88,7 @@ func TestUsageOnNoargs(t *testing.T) {
|
|||
if len(out) != 0 {
|
||||
t.Errorf("wanted nothing on stdout; got:\n%s", out)
|
||||
}
|
||||
if !bytes.Contains(err, []byte("Usage: camput")) {
|
||||
if !bytes.Contains(err, []byte("Usage: pk-put")) {
|
||||
t.Errorf("stderr doesn't contain usage. Got:\n%s", err)
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +113,8 @@ func TestCommandUsage(t *testing.T) {
|
|||
func TestUploadingChangingDirectory(t *testing.T) {
|
||||
// TODO(bradfitz):
|
||||
// $ mkdir /tmp/somedir
|
||||
// $ cp dev-camput /tmp/somedir
|
||||
// $ ./dev-camput -file /tmp/somedir/ 2>&1 | tee /tmp/somedir/log
|
||||
// $ cp dev-pk-put /tmp/somedir
|
||||
// $ ./dev-pk-put -file /tmp/somedir/ 2>&1 | tee /tmp/somedir/log
|
||||
// ... verify it doesn't hang.
|
||||
t.Logf("TODO")
|
||||
}
|
|
@ -28,7 +28,7 @@ import (
|
|||
type deleteCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("delete", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("delete", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(deleteCmd)
|
||||
return cmd
|
||||
})
|
||||
|
@ -39,7 +39,7 @@ func (c *deleteCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *deleteCmd) Usage() {
|
||||
cmdmain.Errorf("Usage: camput [globalopts] delete <blobref1> [blobref2]...")
|
||||
cmdmain.Errorf("Usage: pk-put [globalopts] delete <blobref1> [blobref2]...")
|
||||
}
|
||||
|
||||
func (c *deleteCmd) RunCommand(args []string) error {
|
|
@ -14,20 +14,22 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// TODO(mpl): this doc is not in sync with what the pk-put help outputs. But it should be.
|
||||
|
||||
/*
|
||||
The camput tool mainly pushes blobs, files, and directories. It can also perform various related tasks, such as setting tags, creating permanodes, and creating share blobs.
|
||||
The pk-put tool mainly pushes blobs, files, and directories. It can also perform various related tasks, such as setting tags, creating permanodes, and creating share blobs.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
camput [globalopts] <mode> [commandopts] [commandargs]
|
||||
pk-put [globalopts] <mode> [commandopts] [commandargs]
|
||||
|
||||
Modes:
|
||||
|
||||
delete: Create and upload a delete claim.
|
||||
attr: Add, set, or delete a permanode's attribute.
|
||||
file: Upload file(s).
|
||||
init: Initialize the camput configuration file. With no option, it tries to use the GPG key found in the default identity secret ring.
|
||||
init: Initialize the pk-put configuration file. With no option, it tries to use the GPG key found in the default identity secret ring.
|
||||
permanode: Create and upload a permanode.
|
||||
rawobj: Upload a custom JSON schema blob.
|
||||
share: Grant access to a resource by making a "share" blob.
|
||||
|
@ -35,31 +37,31 @@ Modes:
|
|||
|
||||
Examples:
|
||||
|
||||
camput file [opts] <file(s)/director(ies)
|
||||
camput file --permanode --title='Homedir backup' --tag=backup,homedir $HOME
|
||||
camput file --filenodes /mnt/camera/DCIM
|
||||
pk-put file [opts] <file(s)/director(ies)
|
||||
pk-put file --permanode --title='Homedir backup' --tag=backup,homedir $HOME
|
||||
pk-put file --filenodes /mnt/camera/DCIM
|
||||
|
||||
camput blob <files> (raw, without any metadata)
|
||||
camput blob --permanode --title='My Blob' --tag=backup,my_blob
|
||||
camput blob - (read from stdin)
|
||||
pk-put blob <files> (raw, without any metadata)
|
||||
pk-put blob --permanode --title='My Blob' --tag=backup,my_blob
|
||||
pk-put blob - (read from stdin)
|
||||
|
||||
camput permanode (create a new permanode)
|
||||
camput permanode --title="Some Name" --tag=foo,bar (with attributes added)
|
||||
pk-put permanode (create a new permanode)
|
||||
pk-put permanode --title="Some Name" --tag=foo,bar (with attributes added)
|
||||
|
||||
camput init
|
||||
camput init --gpgkey=XXXXX
|
||||
pk-put init
|
||||
pk-put init --gpgkey=XXXXX
|
||||
|
||||
camput share [opts] <blobref to share via haveref>
|
||||
pk-put share [opts] <blobref to share via haveref>
|
||||
|
||||
camput rawobj (debug command)
|
||||
pk-put rawobj (debug command)
|
||||
|
||||
camput attr <permanode> <name> <value> Set attribute
|
||||
camput attr --add <permanode> <name> <value> Adds attribute (e.g. "tag")
|
||||
camput attr --del <permanode> <name> [<value>] Deletes named attribute [value
|
||||
pk-put attr <permanode> <name> <value> Set attribute
|
||||
pk-put attr --add <permanode> <name> <value> Adds attribute (e.g. "tag")
|
||||
pk-put attr --del <permanode> <name> [<value>] Deletes named attribute [value
|
||||
|
||||
For mode-specific help:
|
||||
|
||||
camput <mode> -help
|
||||
pk-put <mode> -help
|
||||
|
||||
Global options:
|
||||
-help=false: print usage
|
||||
|
@ -72,4 +74,4 @@ Global options:
|
|||
-verbose_http=false: show HTTP request summaries
|
||||
-version=false: show version
|
||||
*/
|
||||
package main // import "perkeep.org/cmd/camput"
|
||||
package main // import "perkeep.org/cmd/pk-put"
|
|
@ -74,7 +74,7 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("file", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("file", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(fileCmd)
|
||||
flags.BoolVar(&cmd.makePermanode, "permanode", false, "Create and associate a new permanode for the uploaded file or directory.")
|
||||
flags.BoolVar(&cmd.filePermanodes, "filenodes", false, "Create (if necessary) content-based permanodes for each uploaded file.")
|
||||
|
@ -115,7 +115,7 @@ func (c *fileCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *fileCmd) Usage() {
|
||||
fmt.Fprintf(cmdmain.Stderr, "Usage: camput [globalopts] file [fileopts] <file/director(ies)>\n")
|
||||
fmt.Fprintf(cmdmain.Stderr, "Usage: pk-put [globalopts] file [fileopts] <file/director(ies)>\n")
|
||||
}
|
||||
|
||||
func (c *fileCmd) Examples() []string {
|
||||
|
@ -395,7 +395,7 @@ func (up *Uploader) uploadNode(ctx context.Context, n *node) (*client.PutResult,
|
|||
case mode&os.ModeNamedPipe != 0: // fifo
|
||||
bb.SetType("fifo")
|
||||
default:
|
||||
return nil, fmt.Errorf("camput.files: unsupported file type %v for file %v", mode, n.fullPath)
|
||||
return nil, fmt.Errorf("pk-put.files: unsupported file type %v for file %v", mode, n.fullPath)
|
||||
case fi.IsDir():
|
||||
ss, err := n.directoryStaticSet()
|
||||
if err != nil {
|
||||
|
@ -436,7 +436,7 @@ func (up *Uploader) statReceiver(n *node) blobserver.StatReceiver {
|
|||
statReceiver := up.altStatReceiver
|
||||
if statReceiver == nil {
|
||||
// TODO(mpl): simplify the altStatReceiver situation as well,
|
||||
// see TODO in cmd/camput/uploader.go
|
||||
// see TODO in cmd/pk-put/uploader.go
|
||||
statReceiver = up.Client
|
||||
}
|
||||
if android.IsChild() && n != nil && n.fi.Mode()&os.ModeType == 0 {
|
|
@ -46,7 +46,7 @@ type initCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("init", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("init", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(initCmd)
|
||||
flags.BoolVar(&cmd.newKey, "newkey", false,
|
||||
"Automatically generate a new identity in a new secret ring at the default location (~/.config/camlistore/identity-secring.gpg on linux).")
|
||||
|
@ -59,11 +59,11 @@ func init() {
|
|||
}
|
||||
|
||||
func (c *initCmd) Describe() string {
|
||||
return "Initialize the camput configuration file. With no option, it tries to use the GPG key found in the default identity secret ring."
|
||||
return "Initialize the pk-put configuration file. With no option, it tries to use the GPG key found in the default identity secret ring."
|
||||
}
|
||||
|
||||
func (c *initCmd) Usage() {
|
||||
usage := "Usage: camput [--server host] init [opts]\n\nExamples:\n"
|
||||
usage := "Usage: pk-put [--server host] init [opts]\n\nExamples:\n"
|
||||
for _, v := range c.usageExamples() {
|
||||
usage += v + "\n"
|
||||
}
|
||||
|
@ -73,10 +73,10 @@ func (c *initCmd) Usage() {
|
|||
func (c *initCmd) usageExamples() []string {
|
||||
var examples []string
|
||||
for _, v := range c.Examples() {
|
||||
examples = append(examples, "camput init "+v)
|
||||
examples = append(examples, "pk-put init "+v)
|
||||
}
|
||||
return append(examples,
|
||||
"camput --server=https://localhost:3179 init --userpass=foo:bar --insecure=true")
|
||||
"pk-put --server=https://localhost:3179 init --userpass=foo:bar --insecure=true")
|
||||
}
|
||||
|
||||
func (c *initCmd) Examples() []string {
|
||||
|
@ -106,7 +106,7 @@ func (c *initCmd) initSecretRing() error {
|
|||
c.secretRing = osutil.SecretRingFile()
|
||||
}
|
||||
if _, err := os.Stat(c.secretRing); err != nil {
|
||||
hint := "\nA GPG key is required, please use 'camput init --newkey'.\n\nOr if you know what you're doing, you can set the global camput flag --secret-keyring, or the CAMLI_SECRET_RING env var, to use your own GPG ring. And --gpgkey=<pubid> or GPGKEY to select which key ID to use."
|
||||
hint := "\nA GPG key is required, please use 'pk-put init --newkey'.\n\nOr if you know what you're doing, you can set the global pk-put flag --secret-keyring, or the CAMLI_SECRET_RING env var, to use your own GPG ring. And --gpgkey=<pubid> or GPGKEY to select which key ID to use."
|
||||
return fmt.Errorf("Could not use secret ring file %v: %v.\n%v", c.secretRing, err, hint)
|
||||
}
|
||||
return nil
|
|
@ -55,7 +55,7 @@ type KvHaveCache struct {
|
|||
|
||||
func NewKvHaveCache(gen string) *KvHaveCache {
|
||||
cleanCacheDir()
|
||||
fullPath := filepath.Join(osutil.CacheDir(), "camput.havecache."+escapeGen(gen)+".leveldb")
|
||||
fullPath := filepath.Join(osutil.CacheDir(), "pk-put.havecache."+escapeGen(gen)+".leveldb")
|
||||
db, err := leveldb.OpenFile(fullPath, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not create/open new have cache at %v, %v", fullPath, err)
|
||||
|
@ -152,7 +152,7 @@ type KvStatCache struct {
|
|||
}
|
||||
|
||||
func NewKvStatCache(gen string) *KvStatCache {
|
||||
fullPath := filepath.Join(osutil.CacheDir(), "camput.statcache."+escapeGen(gen)+".leveldb")
|
||||
fullPath := filepath.Join(osutil.CacheDir(), "pk-put.statcache."+escapeGen(gen)+".leveldb")
|
||||
db, err := leveldb.OpenFile(fullPath, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not create/open new stat cache at %v, %v", fullPath, err)
|
||||
|
@ -376,11 +376,11 @@ func cleanCacheDir() {
|
|||
}
|
||||
|
||||
for _, fi := range fis {
|
||||
if strings.HasPrefix(fi.Name(), "camput.havecache.") {
|
||||
if strings.HasPrefix(fi.Name(), "pk-put.havecache.") {
|
||||
haveCache = append(haveCache, fi)
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(fi.Name(), "camput.statcache.") {
|
||||
if strings.HasPrefix(fi.Name(), "pk-put.statcache.") {
|
||||
statCache = append(statCache, fi)
|
||||
continue
|
||||
}
|
|
@ -36,7 +36,7 @@ type permanodeCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("permanode", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("permanode", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(permanodeCmd)
|
||||
flags.StringVar(&cmd.title, "title", "", "Optional 'title' attribute to set on new permanode")
|
||||
flags.StringVar(&cmd.tag, "tag", "", "Optional tag(s) to set on new permanode; comma separated.")
|
||||
|
@ -51,7 +51,7 @@ func (c *permanodeCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *permanodeCmd) Usage() {
|
||||
cmdmain.Errorf("Usage: camput [globalopts] permanode [permanodeopts]\n")
|
||||
cmdmain.Errorf("Usage: pk-put [globalopts] permanode [permanodeopts]\n")
|
||||
}
|
||||
|
||||
func (c *permanodeCmd) Examples() []string {
|
|
@ -31,7 +31,7 @@ type rawCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("rawobj", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("rawobj", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(rawCmd)
|
||||
flags.StringVar(&cmd.vals, "vals", "", "Pipe-separated key=value properties")
|
||||
flags.BoolVar(&cmd.signed, "signed", true, "whether to sign the JSON object")
|
||||
|
@ -44,7 +44,7 @@ func (c *rawCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *rawCmd) Usage() {
|
||||
cmdmain.Errorf("Usage: camput [globalopts] rawobj [rawopts]\n")
|
||||
cmdmain.Errorf("Usage: pk-put [globalopts] rawobj [rawopts]\n")
|
||||
}
|
||||
|
||||
func (c *rawCmd) Examples() []string {
|
|
@ -27,14 +27,14 @@ import (
|
|||
type removeCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("remove", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("remove", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(removeCmd)
|
||||
return cmd
|
||||
})
|
||||
}
|
||||
|
||||
func (c *removeCmd) Usage() {
|
||||
fmt.Fprintf(cmdmain.Stderr, `Usage: camput remove <blobref(s)>
|
||||
fmt.Fprintf(cmdmain.Stderr, `Usage: pk-put remove <blobref(s)>
|
||||
|
||||
This command is for debugging only. You're not expected to use it in practice.
|
||||
`)
|
|
@ -35,7 +35,7 @@ type shareCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("share", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("share", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(shareCmd)
|
||||
flags.StringVar(&cmd.search, "search", "", "share a search result, rather than a single blob. Should be the JSON representation of a search.SearchQuery (see https://perkeep.org/pkg/search/#SearchQuery for details). Exclusive with, and overrides the <blobref> parameter.")
|
||||
flags.BoolVar(&cmd.transitive, "transitive", false, "share everything reachable from the given blobref")
|
||||
|
@ -49,7 +49,7 @@ func (c *shareCmd) Describe() string {
|
|||
}
|
||||
|
||||
func (c *shareCmd) Usage() {
|
||||
fmt.Fprintf(cmdmain.Stderr, `Usage: camput share [opts] [<blobref>] # blobRef of a file or directory
|
||||
fmt.Fprintf(cmdmain.Stderr, `Usage: pk-put share [opts] [<blobref>] # blobRef of a file or directory
|
||||
`)
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ type claimsCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("claims", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("claims", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(claimsCmd)
|
||||
flags.StringVar(&cmd.server, "server", "", "Server to fetch claims from. "+serverFlagHelp)
|
||||
flags.StringVar(&cmd.attr, "attr", "", "Filter claims about a specific attribute. If empty, all claims are returned.")
|
||||
|
|
|
@ -51,7 +51,7 @@ type dbinitCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("dbinit", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("dbinit", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(dbinitCmd)
|
||||
flags.StringVar(&cmd.user, "user", "root", "Admin user.")
|
||||
flags.StringVar(&cmd.password, "password", "", "Admin password.")
|
||||
|
|
|
@ -48,7 +48,7 @@ type debugSubMode struct {
|
|||
type debugCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("debug", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("debug", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(debugCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ type desCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("describe", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("describe", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(desCmd)
|
||||
flags.StringVar(&cmd.server, "server", "", "Server to query. "+serverFlagHelp)
|
||||
flags.StringVar(&cmd.at, "at", "", "Describe at what point in time. RFC3339 only for now. Empty string means current time.")
|
||||
|
|
|
@ -31,7 +31,7 @@ type discoCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("discovery", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("discovery", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(discoCmd)
|
||||
flags.StringVar(&cmd.server, "server", "", "Server to do discovery against. "+serverFlagHelp)
|
||||
flags.BoolVar(&cmd.httpVer, "httpversion", false, "discover the HTTP version")
|
||||
|
|
|
@ -35,7 +35,7 @@ type reindexdpCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("reindex-diskpacked",
|
||||
cmdmain.RegisterMode("reindex-diskpacked",
|
||||
func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(reindexdpCmd)
|
||||
flags.BoolVar(&cmd.overwrite, "overwrite", false,
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
type dumpconfigCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("dumpconfig", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("dumpconfig", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(dumpconfigCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ var envMap = map[string]func() string{
|
|||
type envCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("env", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("env", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(envCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ type googinitCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("googinit", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("googinit", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(googinitCmd)
|
||||
flags.StringVar(&cmd.storageType, "type", "", "Storage type: drive or cloud")
|
||||
return cmd
|
||||
|
|
|
@ -32,7 +32,7 @@ type indexCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("index", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("index", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(indexCmd)
|
||||
flags.BoolVar(&cmd.wipe, "wipe", false, "Erase and recreate all discovered indexes. NOOP for now.")
|
||||
if debug, _ := strconv.ParseBool(os.Getenv("CAMLI_DEBUG")); debug {
|
||||
|
|
|
@ -39,7 +39,7 @@ type listCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("list", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("list", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &listCmd{
|
||||
syncCmd: &syncCmd{
|
||||
dest: "stdout",
|
||||
|
|
|
@ -34,7 +34,7 @@ type makeStaticCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("makestatic", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("makestatic", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(makeStaticCmd)
|
||||
flags.StringVar(&cmd.server, "server", "", "Server to search. "+serverFlagHelp)
|
||||
return cmd
|
||||
|
|
|
@ -33,7 +33,7 @@ type packBlobsCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("packblobs", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("packblobs", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(packBlobsCmd)
|
||||
flags.StringVar(&cmd.server, "server", "", "Server to search. "+serverFlagHelp)
|
||||
return cmd
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Copyright 2018 The Perkeep Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"perkeep.org/internal/osutil"
|
||||
"perkeep.org/pkg/cmdmain"
|
||||
)
|
||||
|
||||
type putCmd struct {
|
||||
binName string // the executable that is actually called, i.e. "pk-put".
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("put", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return &putCmd{
|
||||
binName: "pk-put",
|
||||
}
|
||||
// TODO(mpl): do cmdmain.ExtraFlagRegistration = client.AddFlags somewhere, so
|
||||
// pk has same global flags as pk-put? (which I think it already does anyway).
|
||||
})
|
||||
}
|
||||
|
||||
func (c *putCmd) Describe() string {
|
||||
return "Create and upload blobs to a server."
|
||||
}
|
||||
|
||||
func (c *putCmd) Usage() {
|
||||
panic("pk put Usage should never get called, as we should always end up calling either pk's or pk-put's usage")
|
||||
}
|
||||
|
||||
func (c *putCmd) RunCommand(args []string) error {
|
||||
// RunCommand is only implemented to satisfy the CommandRunner interface.
|
||||
panic("pk put RunCommand should never get called, as pk is supposed to invoke pk-put instead.")
|
||||
}
|
||||
|
||||
// LookPath returns the full path to the executable that "pk put" actually
|
||||
// calls, i.e. "pk-put".
|
||||
func (c *putCmd) LookPath() (string, error) {
|
||||
fullPath, err := exec.LookPath(c.binName)
|
||||
if err == nil {
|
||||
return fullPath, nil
|
||||
}
|
||||
// If not in PATH, also try in bin dir of Perkeep source tree
|
||||
perkeepPath, err := osutil.GoPackagePath("perkeep.org")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("full path for %v command was not found in either PATH or the bin dir of the source tree", c.binName)
|
||||
}
|
||||
fullPath = filepath.Join(perkeepPath, "bin", c.binName)
|
||||
if _, err := os.Stat(fullPath); err != nil {
|
||||
return "", fmt.Errorf("full path for %v command was not found in either PATH or %v", c.binName, filepath.Join(perkeepPath, "bin"))
|
||||
}
|
||||
return fullPath, nil
|
||||
}
|
|
@ -41,7 +41,7 @@ type searchCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("search", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("search", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(searchCmd)
|
||||
flags.StringVar(&cmd.server, "server", "", "Server to search. "+serverFlagHelp)
|
||||
flags.IntVar(&cmd.limit, "limit", 0, "Limit number of results. 0 is default. Negative means no limit.")
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
type searchDocCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("searchdoc", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("searchdoc", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(searchDocCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ type searchNamesSetCmd struct{}
|
|||
|
||||
func init() {
|
||||
osutil.AddSecretRingFlag()
|
||||
cmdmain.RegisterCommand("named-search-get", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("named-search-get", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(searchNamesGetCmd)
|
||||
})
|
||||
cmdmain.RegisterCommand("named-search-set", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("named-search-set", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(searchNamesSetCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ type syncCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("sync", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("sync", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(syncCmd)
|
||||
flags.StringVar(&cmd.src, "src", "", "Source blobserver. "+serverFlagHelp)
|
||||
flags.StringVar(&cmd.dest, "dest", "", "Destination blobserver (same format as src), or 'stdout' to just enumerate the --src blobs to stdout.")
|
||||
|
|
|
@ -32,7 +32,7 @@ import (
|
|||
type whoamiCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("whoami", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("whoami", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(whoamiCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ type getCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("get", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("get", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &getCmd{
|
||||
env: NewCopyEnv(),
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file adds the "put" subcommand to devcam, to run camput against the dev server.
|
||||
// This file adds the "put" subcommand to devcam, to run pk-put against the dev server.
|
||||
|
||||
package main
|
||||
|
||||
|
@ -40,7 +40,7 @@ type putCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("put", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("put", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &putCmd{
|
||||
env: NewCopyEnv(),
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ func init() {
|
|||
}
|
||||
|
||||
func (c *putCmd) Usage() {
|
||||
fmt.Fprintf(cmdmain.Stderr, "Usage: devcam put [put_opts] camput_args\n")
|
||||
fmt.Fprintf(cmdmain.Stderr, "Usage: devcam put [put_opts] pk-put_args\n")
|
||||
}
|
||||
|
||||
func (c *putCmd) Examples() []string {
|
||||
|
@ -63,7 +63,7 @@ func (c *putCmd) Examples() []string {
|
|||
}
|
||||
|
||||
func (c *putCmd) Describe() string {
|
||||
return "run camput in dev mode."
|
||||
return "run pk-put in dev mode."
|
||||
}
|
||||
|
||||
func (c *putCmd) RunCommand(args []string) error {
|
||||
|
@ -72,8 +72,8 @@ func (c *putCmd) RunCommand(args []string) error {
|
|||
return cmdmain.UsageError(fmt.Sprint(err))
|
||||
}
|
||||
if !*noBuild {
|
||||
if err := build(filepath.Join("cmd", "camput")); err != nil {
|
||||
return fmt.Errorf("Could not build camput: %v", err)
|
||||
if err := build(filepath.Join("cmd", "pk-put")); err != nil {
|
||||
return fmt.Errorf("Could not build pk-put: %v", err)
|
||||
}
|
||||
}
|
||||
c.env.SetCamdevVars(c.altkey)
|
||||
|
@ -88,7 +88,7 @@ func (c *putCmd) RunCommand(args []string) error {
|
|||
blobserver = strings.Replace(blobserver, "http://", "https://", 1)
|
||||
}
|
||||
|
||||
cmdBin := filepath.Join("bin", "camput")
|
||||
cmdBin := filepath.Join("bin", "pk-put")
|
||||
cmdArgs := []string{
|
||||
"-verbose=" + strconv.FormatBool(*cmdmain.FlagVerbose || !quiet),
|
||||
"-server=" + blobserver,
|
||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||
|
||||
/*
|
||||
The devcam tool is a collection of wrappers around the camlistore programs
|
||||
(camistored, camput, pk...) which take care of setup and configuration,
|
||||
(camistored, pk-put, pk...) which take care of setup and configuration,
|
||||
so they can be used by developers to ease hacking on camlistore.
|
||||
|
||||
Usage:
|
||||
|
@ -26,7 +26,7 @@ Usage:
|
|||
Modes:
|
||||
|
||||
get: run camget in dev mode.
|
||||
put: run camput in dev mode.
|
||||
put: run pk-put in dev mode.
|
||||
server: run the stand-alone camlistored in dev mode.
|
||||
|
||||
Examples:
|
||||
|
|
|
@ -85,7 +85,7 @@ type hookCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("hook", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("hook", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &hookCmd{}
|
||||
flags.BoolVar(&cmd.verbose, "verbose", false, "Be verbose.")
|
||||
// TODO(mpl): "-w" flag to run gofmt -w and devcam fixv -w. for now just print instruction.
|
||||
|
|
|
@ -36,7 +36,7 @@ type toolCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("tool", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("tool", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &toolCmd{
|
||||
env: NewCopyEnv(),
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ type mountCmd struct {
|
|||
const mountpoint = "/tmp/pk-mount-dir"
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("mount", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("mount", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &mountCmd{
|
||||
env: NewCopyEnv(),
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ var (
|
|||
type reviewCmd struct{}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("review", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("review", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
return new(reviewCmd)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ type serverCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("server", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("server", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := &serverCmd{
|
||||
env: NewCopyEnv(),
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ type testCmd struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
cmdmain.RegisterCommand("test", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmdmain.RegisterMode("test", func(flags *flag.FlagSet) cmdmain.CommandRunner {
|
||||
cmd := new(testCmd)
|
||||
flags.BoolVar(&cmd.short, "short", false, "Use '-short' with go test.")
|
||||
flags.BoolVar(&cmd.precommit, "precommit", true, "Run the pre-commit githook as part of tests.")
|
||||
|
|
|
@ -62,4 +62,4 @@ on the [mailing list](https://groups.google.com/group/camlistore).
|
|||
## Video tutorials {#tutorials}
|
||||
|
||||
* 2014-03, [Getting started with Camlistore](https://www.youtube.com/watch?v=RUv-8PhnNp8)
|
||||
* 2014-03, [Getting started with camput and the Camlistore client tools](https://www.youtube.com/watch?v=DdccwBFc5ZI)
|
||||
* 2014-03, [Getting started with pk put and the Camlistore client tools](https://www.youtube.com/watch?v=DdccwBFc5ZI)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Configuring a client
|
||||
|
||||
The various clients (camput, camget, pk-mount...) use a common JSON config
|
||||
The various clients (pk put, camget, pk-mount...) use a common JSON config
|
||||
file. This page documents the configuration parameters in that file. Run
|
||||
`pk env clientconfig` to see the default location for that file
|
||||
(**$HOME/.config/camlistore/client-config.json** on linux). In the following
|
||||
|
@ -8,7 +8,7 @@ let **$CONFIGDIR** be the location returned by `pk env configdir`.
|
|||
|
||||
## Generating a default config file
|
||||
|
||||
Run `camput init`.
|
||||
Run `pk put init`.
|
||||
|
||||
On unix,
|
||||
|
||||
|
@ -35,14 +35,14 @@ should look something like:
|
|||
|
||||
### Top-level keys
|
||||
|
||||
* `identity`: your GPG fingerprint. Run `camput init` for help on how to
|
||||
* `identity`: your GPG fingerprint. Run `pk put init` for help on how to
|
||||
generate a new keypair.
|
||||
|
||||
* `identitySecretRing`: Optional. If non-empty, it specifies the location of
|
||||
your GPG secret keyring. Defaults to **$CONFIGDIR/identity-secring.gpg**. Run
|
||||
`camput init` for help on how to generate a new keypair.
|
||||
`pk put init` for help on how to generate a new keypair.
|
||||
|
||||
* `ignoredFiles`: Optional. The list of of files that camput should ignore and
|
||||
* `ignoredFiles`: Optional. The list of of files that pk put should ignore and
|
||||
not try to upload.
|
||||
|
||||
### Servers
|
||||
|
|
|
@ -43,7 +43,7 @@ valid.
|
|||
launched camlistored.
|
||||
|
||||
`CAMLI_DEBUG` (bool)
|
||||
: Used by camlistored and camput to enable additional commandline options.
|
||||
: Used by camlistored and pk put to enable additional commandline options.
|
||||
Used in pkg/schema to enable additional logging.
|
||||
|
||||
`CAMLI_DEBUG_CONFIG` (bool)
|
||||
|
@ -174,7 +174,7 @@ files to be ignored by [pkg/client](/pkg/client) when uploading.
|
|||
|
||||
`CAMLI_NO_FILE_DUP_SEARCH` (bool)
|
||||
: This will cause the search-for-exists-before-upload step to be skipped when
|
||||
camput is uploading files.
|
||||
pk put is uploading files.
|
||||
|
||||
`CAMLI_PPROF_START` (string)
|
||||
: Filename base to write a "<base>.cpu" and "<base>.mem" profile out
|
||||
|
|
|
@ -164,7 +164,7 @@ See the
|
|||
[serverconfig.Publish](https://perkeep.org/pkg/types/serverconfig/#Publish)
|
||||
type for all the configuration parameters.
|
||||
|
||||
One can create any permanode with camput or the UI, and set its camliRoot
|
||||
One can create any permanode with pk put or the UI, and set its camliRoot
|
||||
attribute to the value set in the config, to use it as the root permanode for
|
||||
publishing.
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ in your [server config](/doc/server-config.md).
|
|||
|
||||
Now I want to share Hi.txt with you, so I create a share blob:
|
||||
|
||||
camput share --transitive sha1-0e5e60f367cc8156ae48198c496b2b2ebdf5313d
|
||||
pk put share --transitive sha1-0e5e60f367cc8156ae48198c496b2b2ebdf5313d
|
||||
|
||||
I've created this, and its name is `sha1-102758fb54521cb6540d256098e7c0f1625b33e3`
|
||||
|
||||
|
|
|
@ -38,14 +38,14 @@ pieces and use cases, and where they're at.</p>
|
|||
<table class='status'>
|
||||
<tr><th>Item</th><th>Status</th><th>Notes</th></tr>
|
||||
|
||||
<tr><td><a href="/cmd/camput">camput</a></td><td>99%</td><td>the kitchen sink tool to inject content into a blobserver. Quite good now. Also <a href="https://plus.google.com/u/0/115863474911002159675/posts/DWmyygSrvt7">used by the Android client</a>, as a child process.</td></tr>
|
||||
<tr><td><a href="/cmd/pk put">pk put</a></td><td>99%</td><td>the kitchen sink tool to inject content into a blobserver. Quite good now. Also <a href="https://plus.google.com/u/0/115863474911002159675/posts/DWmyygSrvt7">used by the Android client</a>, as a child process.</td></tr>
|
||||
|
||||
<tr><td><a href="/cmd/camget">camget</a></td><td>10%</td><td>tool to retrieve content from a blobserver.</td></tr>
|
||||
|
||||
<tr><td><a href="/cmd/pk-mount">pk-mount</a></td><td>read-only</td><td>FUSE mounting. Works on Linux and OS X.</td></tr>
|
||||
|
||||
<tr><td><a href="/gw/clients/android">Android Uploader</a></td><td>90%</td><td>UI is kinda ugly in spots but it works and
|
||||
optionally backs up your SD card (photos, etc) to your blob server. Uses camput.
|
||||
optionally backs up your SD card (photos, etc) to your blob server. Uses pk put.
|
||||
Can also work in "Share with Perkeep" mode, one resource at a
|
||||
time.</td></tr>
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ starts with <code>{</code> and is <a href="http://json.org/">valid JSON</a> in i
|
|||
on mutating an object (by all creating new, signed mutation schema blobs),
|
||||
the owner ultimately decides the policies on how the mutations are respected.</p>
|
||||
|
||||
<p>Example permanode blob: (as generated with <code><a href="/cmd/camput">camput</a> --permanode</code>)</p>
|
||||
<p>Example permanode blob: (as generated with <code><a href="/cmd/pk put">pk put</a> --permanode</code>)</p>
|
||||
|
||||
<pre class='sty' style="overflow: auto;">{"camliVersion": 1,
|
||||
"camliSigner": "sha1-c4da9d771661563a27704b91b67989e7ea1e50b8",
|
||||
|
|
|
@ -7,7 +7,7 @@ are various stages of implementation (as of 2013-06-12).
|
|||
|
||||
* **Filesystem backups**: easy initial use case. Since you can easily put
|
||||
[files & directories and such](/doc/schema/) in Perkeep with
|
||||
[camput](/cmd/camput), you can use Perkeep for your backups. Incremental
|
||||
[pk put](/cmd/pk put), you can use Perkeep for your backups. Incremental
|
||||
backups are basically free.
|
||||
|
||||
* **Efficient remote filesystem**: should be easy to do an aggressively caching
|
||||
|
|
4
make.go
4
make.go
|
@ -54,7 +54,7 @@ var (
|
|||
all = flag.Bool("all", false, "Force rebuild of everything (go install -a)")
|
||||
race = flag.Bool("race", false, "Build race-detector version of binaries (they will run slowly)")
|
||||
verbose = flag.Bool("v", strings.Contains(os.Getenv("CAMLI_DEBUG_X"), "makego"), "Verbose mode")
|
||||
targets = flag.String("targets", "", "Optional comma-separated list of targets (i.e go packages) to build and install. '*' builds everything. Empty builds defaults for this platform. Example: perkeep.org/server/camlistored,perkeep.org/cmd/camput")
|
||||
targets = flag.String("targets", "", "Optional comma-separated list of targets (i.e go packages) to build and install. '*' builds everything. Empty builds defaults for this platform. Example: perkeep.org/server/camlistored,perkeep.org/cmd/pk-put")
|
||||
quiet = flag.Bool("quiet", false, "Don't print anything unless there's a failure.")
|
||||
buildARCH = flag.String("arch", runtime.GOARCH, "Architecture to build for.")
|
||||
buildOS = flag.String("os", runtime.GOOS, "Operating system to build for.")
|
||||
|
@ -107,7 +107,7 @@ func main() {
|
|||
targs := []string{
|
||||
"perkeep.org/dev/devcam",
|
||||
"perkeep.org/cmd/camget",
|
||||
"perkeep.org/cmd/camput",
|
||||
"perkeep.org/cmd/pk-put",
|
||||
"perkeep.org/cmd/pk",
|
||||
"perkeep.org/cmd/pk-deploy",
|
||||
"perkeep.org/server/camlistored",
|
||||
|
|
|
@ -425,7 +425,7 @@ func packBinaries(ctxDir string) {
|
|||
binaries := map[string]bool{
|
||||
exeName("camlistored"): false,
|
||||
exeName("camget"): false,
|
||||
exeName("camput"): false,
|
||||
exeName("pk-put"): false,
|
||||
exeName("pk"): false,
|
||||
exeName("publisher"): false,
|
||||
}
|
||||
|
|
|
@ -286,7 +286,7 @@ func TLSConfig() (*tls.Config, error) {
|
|||
return cfg, nil
|
||||
}
|
||||
|
||||
// NoteFileUploaded is a hook for camput to report that a file
|
||||
// NoteFileUploaded is a hook for pk-put to report that a file
|
||||
// was uploaded. TODO: move this to pkg/client/android probably.
|
||||
func NoteFileUploaded(fullPath string, uploaded bool) {
|
||||
if !IsChild() {
|
||||
|
@ -302,7 +302,7 @@ func NoteFileUploaded(fullPath string, uploaded bool) {
|
|||
|
||||
// StatusReceiver is a blobserver.StatReceiver wrapper that
|
||||
// reports the full filename path and size of uploaded blobs.
|
||||
// The android app wrapping camput watches stdout for this, for progress bars.
|
||||
// The android app wrapping pk-put watches stdout for this, for progress bars.
|
||||
type StatusReceiver struct {
|
||||
Sr blobserver.StatReceiver
|
||||
Path string
|
||||
|
|
|
@ -114,8 +114,8 @@ type Client struct {
|
|||
insecureAnyTLSCert bool
|
||||
|
||||
initIgnoredFilesOnce sync.Once
|
||||
// list of files that camput should ignore.
|
||||
// Defaults to empty, but camput init creates a config with a non
|
||||
// list of files that pk-put should ignore.
|
||||
// Defaults to empty, but pk-put init creates a config with a non
|
||||
// empty list.
|
||||
// See IsIgnoredFile for the matching rules.
|
||||
ignoredFiles []string
|
||||
|
@ -255,7 +255,7 @@ func (c *Client) NewPathClient(path string) (*Client, error) {
|
|||
// TransportConfig contains options for how HTTP requests are made.
|
||||
type TransportConfig struct {
|
||||
// Proxy optionally specifies the Proxy for the transport. Useful with
|
||||
// camput for debugging even localhost requests.
|
||||
// pk-put for debugging even localhost requests.
|
||||
Proxy func(*http.Request) (*url.URL, error)
|
||||
Verbose bool // Verbose enables verbose logging of HTTP requests.
|
||||
}
|
||||
|
@ -1487,7 +1487,7 @@ func (c *Client) UploadPlannedPermanode(ctx context.Context, key string, sigTime
|
|||
return c.uploadString(ctx, signed, true)
|
||||
}
|
||||
|
||||
// IsIgnoredFile returns whether the file at fullpath should be ignored by camput.
|
||||
// IsIgnoredFile returns whether the file at fullpath should be ignored by pk-put.
|
||||
// The fullpath is checked against the ignoredFiles list, trying the following rules in this order:
|
||||
// 1) star-suffix style matching (.e.g *.jpg).
|
||||
// 2) Shell pattern match as done by http://golang.org/pkg/path/filepath/#Match
|
||||
|
|
|
@ -93,9 +93,9 @@ func (c *Client) parseConfig() {
|
|||
if c != nil && c.isSharePrefix {
|
||||
return
|
||||
}
|
||||
errMsg := fmt.Sprintf("Client configuration file %v does not exist. See 'camput init' to generate it.", configPath)
|
||||
errMsg := fmt.Sprintf("Client configuration file %v does not exist. See 'pk-put init' to generate it.", configPath)
|
||||
if keyID := serverKeyId(); keyID != "" {
|
||||
hint := fmt.Sprintf("\nThe key id %v was found in the server config %v, so you might want:\n'camput init -gpgkey %v'", keyID, osutil.UserServerConfigPath(), keyID)
|
||||
hint := fmt.Sprintf("\nThe key id %v was found in the server config %v, so you might want:\n'pk-put init -gpgkey %v'", keyID, osutil.UserServerConfigPath(), keyID)
|
||||
errMsg += hint
|
||||
}
|
||||
log.Fatal(errMsg)
|
||||
|
@ -220,7 +220,7 @@ func printConfigChangeHelp(conf jsonconfig.Obj) {
|
|||
}
|
||||
}
|
||||
if oldConfig {
|
||||
configChangedMsg += "Please see https://perkeep.org/doc/client-config, or use camput init to recreate a default one."
|
||||
configChangedMsg += "Please see https://perkeep.org/doc/client-config, or use pk-put init to recreate a default one."
|
||||
log.Print(configChangedMsg)
|
||||
}
|
||||
}
|
||||
|
@ -414,7 +414,7 @@ func (c *Client) initSignerPublicKeyBlobref() {
|
|||
configOnce.Do(parseConfig)
|
||||
keyID = config.Identity
|
||||
if keyID == "" {
|
||||
log.Fatalf("No 'identity' key in JSON configuration file %q; have you run \"camput init\"?", osutil.UserClientConfigPath())
|
||||
log.Fatalf("No 'identity' key in JSON configuration file %q; have you run \"pk-put init\"?", osutil.UserClientConfigPath())
|
||||
}
|
||||
}
|
||||
keyRing := c.SecretRingFile()
|
||||
|
|
|
@ -447,7 +447,7 @@ type FileUploadOptions struct {
|
|||
// the server, they're not uploaded.
|
||||
//
|
||||
// Note: this method is still a work in progress, and might change to accommodate
|
||||
// the needs of camput file.
|
||||
// the needs of pk-put file.
|
||||
func (c *Client) UploadFile(ctx context.Context, filename string, contents io.Reader, opts *FileUploadOptions) (blob.Ref, error) {
|
||||
fileMap := schema.NewFileMap(filename)
|
||||
if opts != nil && opts.FileInfo != nil {
|
||||
|
@ -483,7 +483,7 @@ func (c *Client) UploadFile(ctx context.Context, filename string, contents io.Re
|
|||
return schema.WriteFileMap(ctx, c, fileMap, contents)
|
||||
}
|
||||
|
||||
// TODO(mpl): replace up.wholeFileDigest in camput with c.wholeRef maybe.
|
||||
// TODO(mpl): replace up.wholeFileDigest in pk-put with c.wholeRef maybe.
|
||||
|
||||
// wholeRef returns the blob ref(s) of the regular file's contents
|
||||
// as if it were one entire blob (ignoring blob size limits).
|
||||
|
|
|
@ -24,8 +24,10 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"perkeep.org/pkg/buildinfo"
|
||||
|
@ -68,6 +70,9 @@ var (
|
|||
modeCommand = make(map[string]CommandRunner)
|
||||
modeFlags = make(map[string]*flag.FlagSet)
|
||||
wantHelp = make(map[string]*bool)
|
||||
// asNewCommand stores whether the mode should actually be run as a new
|
||||
// independent command.
|
||||
asNewCommand = make(map[string]bool)
|
||||
|
||||
// Indirections for replacement by tests
|
||||
Stderr io.Writer = os.Stderr
|
||||
|
@ -93,6 +98,13 @@ type CommandRunner interface {
|
|||
RunCommand(args []string) error
|
||||
}
|
||||
|
||||
// ExecRunner is the type that a command mode should implement when that mode
|
||||
// just calls a new executable that will run as a new command.
|
||||
type ExecRunner interface {
|
||||
CommandRunner
|
||||
LookPath() (string, error)
|
||||
}
|
||||
|
||||
type exampler interface {
|
||||
Examples() []string
|
||||
}
|
||||
|
@ -101,9 +113,9 @@ type describer interface {
|
|||
Describe() string
|
||||
}
|
||||
|
||||
// RegisterCommand adds a mode to the list of modes for the main command.
|
||||
// RegisterMode adds a mode to the list of modes for the main command.
|
||||
// It is meant to be called in init() for each subcommand.
|
||||
func RegisterCommand(mode string, makeCmd func(Flags *flag.FlagSet) CommandRunner) {
|
||||
func RegisterMode(mode string, makeCmd func(Flags *flag.FlagSet) CommandRunner) {
|
||||
if _, dup := modeCommand[mode]; dup {
|
||||
log.Fatalf("duplicate command %q registered", mode)
|
||||
}
|
||||
|
@ -117,6 +129,15 @@ func RegisterCommand(mode string, makeCmd func(Flags *flag.FlagSet) CommandRunne
|
|||
modeCommand[mode] = makeCmd(flags)
|
||||
}
|
||||
|
||||
// RegisterCommand adds a mode to the list of modes for the main command, and
|
||||
// also specifies that this mode is just another executable that runs as a new
|
||||
// cmdmain command. The executable to run is determined by the LookPath implementation
|
||||
// for this mode.
|
||||
func RegisterCommand(mode string, makeCmd func(Flags *flag.FlagSet) CommandRunner) {
|
||||
RegisterMode(mode, makeCmd)
|
||||
asNewCommand[mode] = true
|
||||
}
|
||||
|
||||
func hasFlags(flags *flag.FlagSet) bool {
|
||||
any := false
|
||||
flags.VisitAll(func(*flag.Flag) {
|
||||
|
@ -249,10 +270,22 @@ func Main() {
|
|||
usage(fmt.Sprintf("Unknown mode %q", mode))
|
||||
}
|
||||
|
||||
if _, ok := asNewCommand[mode]; ok {
|
||||
runAsNewCommand(cmd, mode)
|
||||
return
|
||||
}
|
||||
|
||||
cmdFlags := modeFlags[mode]
|
||||
cmdFlags.SetOutput(Stderr)
|
||||
err := cmdFlags.Parse(args[1:])
|
||||
if err != nil {
|
||||
// We want -h to behave as -help, but without having to define another flag for
|
||||
// it, so we handle it here.
|
||||
// TODO(mpl): maybe even remove -help and just let them both be handled here?
|
||||
if err == flag.ErrHelp {
|
||||
help(mode)
|
||||
return
|
||||
}
|
||||
err = ErrUsage
|
||||
} else {
|
||||
if *wantHelp[mode] {
|
||||
|
@ -285,6 +318,39 @@ func Main() {
|
|||
}
|
||||
}
|
||||
|
||||
// runAsNewCommand runs the executable specified by cmd's LookPath, which means
|
||||
// cmd must implement the ExecRunner interface. The executable must be a binary of
|
||||
// a program that runs Main.
|
||||
func runAsNewCommand(cmd CommandRunner, mode string) {
|
||||
execCmd, ok := cmd.(ExecRunner)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("%v does not implement ExecRunner", mode))
|
||||
}
|
||||
cmdPath, err := execCmd.LookPath()
|
||||
if err != nil {
|
||||
Errorf("Error: %v\n", err)
|
||||
Exit(2)
|
||||
}
|
||||
allArgs := shiftFlags(mode)
|
||||
if err := runExec(cmdPath, allArgs, newCopyEnv()); err != nil {
|
||||
panic(fmt.Sprintf("running %v should have ended with an os.Exit, and not leave us with that error: %v", cmdPath, err))
|
||||
}
|
||||
}
|
||||
|
||||
// shiftFlags prepends all the arguments (global flags) passed before the given
|
||||
// mode to the list of arguments after that mode, and returns that list.
|
||||
func shiftFlags(mode string) []string {
|
||||
modePos := 0
|
||||
for k, v := range os.Args {
|
||||
if v == mode {
|
||||
modePos = k
|
||||
break
|
||||
}
|
||||
}
|
||||
globalFlags := os.Args[1:modePos]
|
||||
return append(globalFlags, os.Args[modePos+1:]...)
|
||||
}
|
||||
|
||||
// Errorf prints to Stderr, regardless of FlagVerbose.
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
fmt.Fprintf(Stderr, format, args...)
|
||||
|
@ -304,3 +370,54 @@ func Logf(format string, v ...interface{}) {
|
|||
}
|
||||
logger.Printf(format, v...)
|
||||
}
|
||||
|
||||
// sysExec is set to syscall.Exec on platforms that support it.
|
||||
var sysExec func(argv0 string, argv []string, envv []string) (err error)
|
||||
|
||||
// runExec execs bin. If the platform doesn't support exec, it runs it and waits
|
||||
// for it to finish.
|
||||
func runExec(bin string, args []string, e *env) error {
|
||||
if sysExec != nil {
|
||||
sysExec(bin, append([]string{filepath.Base(bin)}, args...), e.flat())
|
||||
}
|
||||
|
||||
cmd := exec.Command(bin, args...)
|
||||
cmd.Env = e.flat()
|
||||
cmd.Stdout = Stdout
|
||||
cmd.Stderr = Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
type env struct {
|
||||
m map[string]string
|
||||
order []string
|
||||
}
|
||||
|
||||
func (e *env) set(k, v string) {
|
||||
_, dup := e.m[k]
|
||||
e.m[k] = v
|
||||
if !dup {
|
||||
e.order = append(e.order, k)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *env) flat() []string {
|
||||
vv := make([]string, 0, len(e.order))
|
||||
for _, k := range e.order {
|
||||
if v, ok := e.m[k]; ok {
|
||||
vv = append(vv, k+"="+v)
|
||||
}
|
||||
}
|
||||
return vv
|
||||
}
|
||||
|
||||
func newCopyEnv() *env {
|
||||
e := &env{make(map[string]string), nil}
|
||||
for _, kv := range os.Environ() {
|
||||
eq := strings.Index(kv, "=")
|
||||
if eq > 0 {
|
||||
e.set(kv[:eq], kv[eq+1:])
|
||||
}
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2018 The Perkeep Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmdmain
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
sysExec = syscall.Exec
|
||||
}
|
|
@ -69,9 +69,9 @@ const (
|
|||
// If set, it should be of a "file" schema blob referencing the tweets.zip
|
||||
// file that Twitter makes available for the full archive download.
|
||||
// The Twitter API doesn't go back forever in time, so if you started using
|
||||
// the Perkeep importer too late, you need to "camput file tweets.zip"
|
||||
// the Perkeep importer too late, you need to "pk-put file tweets.zip"
|
||||
// once downloading it from Twitter, and then:
|
||||
// $ camput attr <acct-permanode> twitterArchiveZipFileRef <zip-fileref>
|
||||
// $ pk-put attr <acct-permanode> twitterArchiveZipFileRef <zip-fileref>
|
||||
// ... and re-do an import.
|
||||
acctAttrTweetZip = "twitterArchiveZipFileRef"
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ func TestCamgetSymlink(t *testing.T) {
|
|||
t.Fatalf("os.Symlink(): %v", err)
|
||||
}
|
||||
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", srcDir))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", srcDir))
|
||||
// TODO(mpl): rm call and delete pkg.
|
||||
asserts.ExpectBool(t, true, out != "", "camput")
|
||||
asserts.ExpectBool(t, true, out != "", "pk-put")
|
||||
br := strings.Split(out, "\n")[0]
|
||||
dstDir, err := ioutil.TempDir("", "camget-test-")
|
||||
if err != nil {
|
||||
|
@ -106,7 +106,7 @@ func TestCamgetFIFO(t *testing.T) {
|
|||
|
||||
// Upload the fifo
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", fifo))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", fifo))
|
||||
br := strings.Split(out, "\n")[0]
|
||||
|
||||
// Try and get it back
|
||||
|
@ -139,7 +139,7 @@ func TestCamgetSocket(t *testing.T) {
|
|||
|
||||
// Upload the socket
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", socket))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", socket))
|
||||
br := strings.Split(out, "\n")[0]
|
||||
|
||||
// Try and get it back
|
||||
|
@ -189,7 +189,7 @@ func TestCamgetFile(t *testing.T) {
|
|||
}
|
||||
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", filename))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", filename))
|
||||
|
||||
br := strings.Split(out, "\n")[0]
|
||||
_ = test.MustRunCmd(t, w.Cmd("camget", "-o", outDir, "-contents", br))
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
)
|
||||
|
||||
// Test that running:
|
||||
// $ camput permanode
|
||||
// $ pk-put permanode
|
||||
// ... creates and uploads a permanode, and that we can camget it back.
|
||||
func TestCamputPermanode(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
|
@ -58,7 +58,7 @@ func TestCamputPermanode(t *testing.T) {
|
|||
func TestWebsocketQuery(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
pn := w.NewPermanode(t)
|
||||
test.MustRunCmd(t, w.Cmd("camput", "attr", pn.String(), "tag", "foo"))
|
||||
test.MustRunCmd(t, w.Cmd("pk-put", "attr", pn.String(), "tag", "foo"))
|
||||
|
||||
check := func(err error) {
|
||||
if err != nil {
|
||||
|
@ -123,10 +123,10 @@ func TestWebsocketQuery(t *testing.T) {
|
|||
func TestInternalHandler(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
tests := map[string]int{
|
||||
"/no-http-storage/": 401,
|
||||
"/no-http-handler/": 401,
|
||||
"/good-status/": 200,
|
||||
"/bs-and-maybe-also-index/camli": 400,
|
||||
"/no-http-storage/": 401,
|
||||
"/no-http-handler/": 401,
|
||||
"/good-status/": 200,
|
||||
"/bs-and-maybe-also-index/camli": 400,
|
||||
"/bs/camli/sha1-b2201302e129a4396a323cb56283cddeef11bbe8": 404,
|
||||
"/no-http-storage/camli/sha1-b2201302e129a4396a323cb56283cddeef11bbe8": 401,
|
||||
}
|
||||
|
@ -178,8 +178,8 @@ func mustWriteFile(t *testing.T, path, contents string) {
|
|||
}
|
||||
}
|
||||
|
||||
// Run camput in the environment it runs in under the Android app.
|
||||
// This matches how camput is used in UploadThread.java.
|
||||
// Run pk-put in the environment it runs in under the Android app.
|
||||
// This matches how pk-put is used in UploadThread.java.
|
||||
func TestAndroidCamputFile(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
// UploadThread.java sets:
|
||||
|
@ -193,7 +193,7 @@ func TestAndroidCamputFile(t *testing.T) {
|
|||
"CAMPUT_ANDROID_OUTPUT=1",
|
||||
"CAMLI_CACHE_DIR=" + cacheDir,
|
||||
}
|
||||
cmd := w.CmdWithEnv("camput",
|
||||
cmd := w.CmdWithEnv("pk-put",
|
||||
env,
|
||||
"--server="+w.ServerBaseURL(),
|
||||
"file",
|
||||
|
@ -259,10 +259,10 @@ func TestAndroidCamputFile(t *testing.T) {
|
|||
}()
|
||||
select {
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("timeout waiting for camput to end")
|
||||
t.Fatal("timeout waiting for pk-put to end")
|
||||
case err := <-waitc:
|
||||
if err != nil {
|
||||
t.Errorf("camput exited uncleanly: %v", err)
|
||||
t.Errorf("pk-put exited uncleanly: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ func mkTmpFIFO(t *testing.T) (path string, cleanup func()) {
|
|||
return
|
||||
}
|
||||
|
||||
// Test that `camput' can upload fifos correctly.
|
||||
// Test that `pk-put' can upload fifos correctly.
|
||||
func TestCamputFIFO(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.SkipNow()
|
||||
|
@ -61,7 +61,7 @@ func TestCamputFIFO(t *testing.T) {
|
|||
|
||||
// Can we successfully upload a fifo?
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", fifo))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", fifo))
|
||||
|
||||
br := strings.Split(out, "\n")[0]
|
||||
out = test.MustRunCmd(t, w.Cmd("camget", br))
|
||||
|
@ -88,7 +88,7 @@ func mkTmpSocket(t *testing.T) (path string, cleanup func()) {
|
|||
return
|
||||
}
|
||||
|
||||
// Test that `camput' can upload sockets correctly.
|
||||
// Test that `pk-put' can upload sockets correctly.
|
||||
func TestCamputSocket(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.SkipNow()
|
||||
|
@ -99,45 +99,45 @@ func TestCamputSocket(t *testing.T) {
|
|||
|
||||
// Can we successfully upload a socket?
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", socket))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", socket))
|
||||
|
||||
br := strings.Split(out, "\n")[0]
|
||||
out = test.MustRunCmd(t, w.Cmd("camget", br))
|
||||
t.Logf("Retrieved stored socket schema: %s", out)
|
||||
}
|
||||
|
||||
// Test that camput twice on the same file only uploads once.
|
||||
// Test that pk-put twice on the same file only uploads once.
|
||||
func TestCamputUploadOnce(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
|
||||
camputCmd := func() *exec.Cmd {
|
||||
pkputCmd := func() *exec.Cmd {
|
||||
// Use --contents_only because if test is run from devcam,
|
||||
// server-config.json is going to be the one from within the fake gopath,
|
||||
// hence with a different cTime and with a different blobRef everytime.
|
||||
// Also, CAMLI_DEBUG is needed for --contents_only flag.
|
||||
return w.CmdWithEnv("camput", append(os.Environ(), "CAMLI_DEBUG=1"), "file", "--contents_only=true", filepath.FromSlash("../testdata/server-config.json"))
|
||||
return w.CmdWithEnv("pk-put", append(os.Environ(), "CAMLI_DEBUG=1"), "file", "--contents_only=true", filepath.FromSlash("../testdata/server-config.json"))
|
||||
}
|
||||
wantBlobRef := "sha1-381c42a63078ef49a2f1808318dbbafbb31a81d5"
|
||||
cmd := camputCmd()
|
||||
cmd := pkputCmd()
|
||||
out := test.MustRunCmd(t, cmd)
|
||||
out = strings.TrimSpace(out)
|
||||
if out != wantBlobRef {
|
||||
t.Fatalf("wrong camput output; wanted %v, got %v", wantBlobRef, out)
|
||||
t.Fatalf("wrong pk-put output; wanted %v, got %v", wantBlobRef, out)
|
||||
}
|
||||
|
||||
cmd = camputCmd()
|
||||
cmd = pkputCmd()
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatalf("second camput failed: %v, stdout: %v, stderr: %v", err, output, stderr.String())
|
||||
t.Fatalf("second pk-put failed: %v, stdout: %v, stderr: %v", err, output, stderr.String())
|
||||
}
|
||||
out = strings.TrimSpace(string(output))
|
||||
if out != wantBlobRef {
|
||||
t.Fatalf("wrong 2nd camput output; wanted %v, got %v", wantBlobRef, out)
|
||||
t.Fatalf("wrong 2nd pk-put output; wanted %v, got %v", wantBlobRef, out)
|
||||
}
|
||||
wantStats := `[uploadRequests=[blobs=0 bytes=0] uploads=[blobs=0 bytes=0]]`
|
||||
if !strings.Contains(stderr.String(), wantStats) {
|
||||
t.Fatalf("Wrong stats for 2nd camput upload; wanted %v, got %v", wantStats, out)
|
||||
t.Fatalf("Wrong stats for 2nd pk-put upload; wanted %v, got %v", wantStats, out)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ func benchmarkWrite(b *testing.B, cfg string) {
|
|||
b.Fatalf("could not start server for config: %v\nError: %v", cfg, err)
|
||||
}
|
||||
b.StartTimer()
|
||||
test.MustRunCmd(b, w.Cmd("camput", "file", testFile))
|
||||
test.MustRunCmd(b, w.Cmd("pk-put", "file", testFile))
|
||||
b.StopTimer()
|
||||
w.Stop()
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ func parseJSON(s string) map[string]interface{} {
|
|||
func TestSetNamed(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
// Needed to upload the owner public key
|
||||
runCmd(t, w, "camput", "permanode")
|
||||
runCmd(t, w, "pk-put", "permanode")
|
||||
|
||||
runCmd(t, w, "pk", "named-search-set", "bar", "is:image and tag:bar")
|
||||
gno := runCmd(t, w, "pk", "named-search-get", "bar")
|
||||
|
@ -58,16 +58,16 @@ func TestSetNamed(t *testing.T) {
|
|||
func TestGetNamed(t *testing.T) {
|
||||
w := test.GetWorld(t)
|
||||
|
||||
putExprCmd := w.Cmd("camput", "blob", "-")
|
||||
putExprCmd := w.Cmd("pk-put", "blob", "-")
|
||||
putExprCmd.Stdin = strings.NewReader("is:pano")
|
||||
ref, err := test.RunCmd(putExprCmd)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pn := runCmd(t, w, "camput", "permanode")
|
||||
runCmd(t, w, "camput", "attr", strings.TrimSpace(pn), "camliNamedSearch", "foo")
|
||||
runCmd(t, w, "camput", "attr", strings.TrimSpace(pn), "camliContent", strings.TrimSpace(ref))
|
||||
pn := runCmd(t, w, "pk-put", "permanode")
|
||||
runCmd(t, w, "pk-put", "attr", strings.TrimSpace(pn), "camliNamedSearch", "foo")
|
||||
runCmd(t, w, "pk-put", "attr", strings.TrimSpace(pn), "camliContent", strings.TrimSpace(ref))
|
||||
gno := runCmd(t, w, "pk", "named-search-get", "foo")
|
||||
gnr := parseJSON(gno)
|
||||
if gnr["named"] != "foo" || gnr["substitute"] != "is:pano" {
|
||||
|
@ -79,7 +79,7 @@ func TestNamedSearch(t *testing.T) {
|
|||
w := test.GetWorld(t)
|
||||
|
||||
runCmd(t, w, "pk", "named-search-set", "favorite", "tag:cats")
|
||||
pn := runCmd(t, w, "camput", "permanode", "-title", "Felix", "-tag", "cats")
|
||||
pn := runCmd(t, w, "pk-put", "permanode", "-title", "Felix", "-tag", "cats")
|
||||
_, lines, err := bufio.ScanLines([]byte(pn), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -97,7 +97,7 @@ func TestNestedNamedSearch(t *testing.T) {
|
|||
|
||||
runCmd(t, w, "pk", "named-search-set", "favorite", "tag:cats")
|
||||
runCmd(t, w, "pk", "named-search-set", "mybest", "named:favorite")
|
||||
pn := runCmd(t, w, "camput", "permanode", "-title", "Felix", "-tag", "cats")
|
||||
pn := runCmd(t, w, "pk-put", "permanode", "-title", "Felix", "-tag", "cats")
|
||||
_, lines, err := bufio.ScanLines([]byte(pn), false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -45,7 +45,7 @@ func tempDir(t *testing.T) (path string, cleanup func()) {
|
|||
return
|
||||
}
|
||||
|
||||
// Test that we can camput and camget a file whose name is not utf8,
|
||||
// Test that we can pk-put and camget a file whose name is not utf8,
|
||||
// that we don't panic in the process and that the results are
|
||||
// correct.
|
||||
func TestNonUTF8FileName(t *testing.T) {
|
||||
|
@ -69,10 +69,10 @@ func TestNonUTF8FileName(t *testing.T) {
|
|||
fd.Close()
|
||||
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", fd.Name()))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", fd.Name()))
|
||||
br := strings.Split(out, "\n")[0]
|
||||
|
||||
// camput was a success. Can we get the file back in another directory?
|
||||
// pk-put was a success. Can we get the file back in another directory?
|
||||
dstDir, cleanup := tempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
|
@ -84,7 +84,7 @@ func TestNonUTF8FileName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that we can camput and camget a symbolic link whose target is
|
||||
// Test that we can pk-put and camget a symbolic link whose target is
|
||||
// not utf8, that we do no panic in the process and that the results
|
||||
// are correct.
|
||||
func TestNonUTF8SymlinkTarget(t *testing.T) {
|
||||
|
@ -113,7 +113,7 @@ func TestNonUTF8SymlinkTarget(t *testing.T) {
|
|||
}
|
||||
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", filepath.Join(srcDir, "link")))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", filepath.Join(srcDir, "link")))
|
||||
br := strings.Split(out, "\n")[0]
|
||||
|
||||
// See if we can camget it back correctly
|
||||
|
|
|
@ -43,10 +43,10 @@ func TestDirSharing(t *testing.T) {
|
|||
|
||||
func share(t *testing.T, file string) {
|
||||
w := test.GetWorld(t)
|
||||
out := test.MustRunCmd(t, w.Cmd("camput", "file", file))
|
||||
out := test.MustRunCmd(t, w.Cmd("pk-put", "file", file))
|
||||
fileRef := strings.Split(out, "\n")[0]
|
||||
|
||||
out = test.MustRunCmd(t, w.Cmd("camput", "share", "-transitive", fileRef))
|
||||
out = test.MustRunCmd(t, w.Cmd("pk-put", "share", "-transitive", fileRef))
|
||||
shareRef := strings.Split(out, "\n")[0]
|
||||
|
||||
testDir, err := ioutil.TempDir("", "camli-share-test-")
|
||||
|
|
|
@ -41,7 +41,7 @@ import (
|
|||
// World defines an integration test world.
|
||||
//
|
||||
// It's used to run the actual Perkeep binaries (camlistored,
|
||||
// camput, camget, pk, etc) together in large tests, including
|
||||
// pk-put, camget, pk, etc) together in large tests, including
|
||||
// building them, finding them, and wiring them up in an isolated way.
|
||||
type World struct {
|
||||
srcRoot string // typically $GOPATH[0]/src/perkeep.org
|
||||
|
@ -249,10 +249,10 @@ func (w *World) NewPermanode(t *testing.T) blob.Ref {
|
|||
if err := w.Ping(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out := MustRunCmd(t, w.Cmd("camput", "permanode"))
|
||||
out := MustRunCmd(t, w.Cmd("pk-put", "permanode"))
|
||||
br, ok := blob.Parse(strings.TrimSpace(out))
|
||||
if !ok {
|
||||
t.Fatalf("Expected permanode in camput stdout; got %q", out)
|
||||
t.Fatalf("Expected permanode in pk-put stdout; got %q", out)
|
||||
}
|
||||
return br
|
||||
}
|
||||
|
@ -272,10 +272,10 @@ func (w *World) CmdWithEnv(binary string, env []string, args ...string) *exec.Cm
|
|||
}
|
||||
var cmd *exec.Cmd
|
||||
switch binary {
|
||||
case "camget", "camput", "pk", "pk-mount":
|
||||
// TODO(mpl): lift the camput restriction when we have a unified logging mechanism
|
||||
if binary == "camput" && !hasVerbose() {
|
||||
// camput and pk are the only ones to have a -verbose flag through cmdmain
|
||||
case "camget", "pk-put", "pk", "pk-mount":
|
||||
// TODO(mpl): lift the pk-put restriction when we have a unified logging mechanism
|
||||
if binary == "pk-put" && !hasVerbose() {
|
||||
// pk-put and pk are the only ones to have a -verbose flag through cmdmain
|
||||
// but pk is never used. (and pk-mount does not even have a -verbose).
|
||||
args = append([]string{"-verbose"}, args...)
|
||||
}
|
||||
|
@ -326,7 +326,7 @@ func GetWorldMaybe(t *testing.T) *World {
|
|||
}
|
||||
|
||||
// RunCmd runs c (which is assumed to be something short-lived, like a
|
||||
// camput or camget command), capturing its stdout for return, and
|
||||
// pk-put or camget command), capturing its stdout for return, and
|
||||
// also capturing its stderr, just in the case of errors.
|
||||
// If there's an error, the return error fully describes the command and
|
||||
// all output.
|
||||
|
|
|
@ -31,7 +31,7 @@ var (
|
|||
ErrClientNoServer = addCamError("client-no-server", funcStr(func() string {
|
||||
return fmt.Sprintf("No valid server defined. It can be set with the CAMLI_SERVER environment variable, or the --server flag, or in the \"servers\" section of %q (see https://camlistore.org/doc/client-config).", osutil.UserClientConfigPath())
|
||||
}))
|
||||
ErrClientNoPublicKey = addCamError("client-no-public-key", str("No public key configured: see 'camput init'."))
|
||||
ErrClientNoPublicKey = addCamError("client-no-public-key", str("No public key configured: see 'pk-put init'."))
|
||||
)
|
||||
|
||||
type str string
|
||||
|
|
|
@ -34,7 +34,7 @@ type Config struct {
|
|||
Servers map[string]*Server `json:"servers"` // maps server alias to server config.
|
||||
Identity string `json:"identity"` // GPG identity.
|
||||
IdentitySecretRing string `json:"identitySecretRing,omitempty"` // location of the secret ring file.
|
||||
IgnoredFiles []string `json:"ignoredFiles,omitempty"` // list of files that camput should ignore.
|
||||
IgnoredFiles []string `json:"ignoredFiles,omitempty"` // list of files that pk-put should ignore.
|
||||
}
|
||||
|
||||
// Server holds the values specific to each server found in the JSON client
|
||||
|
|
Loading…
Reference in New Issue