Skip to content

Commit

Permalink
CLI: template option with no ranges
Browse files Browse the repository at this point in the history
* support prefix-only `--template`; add usage examples

Signed-off-by: Alex Aizman <[email protected]>
  • Loading branch information
alex-aizman committed Dec 12, 2023
1 parent 07e1e0b commit f83bd00
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 31 deletions.
14 changes: 10 additions & 4 deletions cmd/cli/cli/arch_hdlr.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ func putApndArchHandler(c *cli.Context) (err error) {
// a) csv of files and/or directories (names) from the first arg, e.g. "f1[,f2...]" dst-bucket[/prefix]
// b) csv from '--list' flag
return verbList(c, &a, a.src.fdnames, a.dst.bck, a.archpath /*append pref*/, incl)
case a.pt != nil:
case a.pt != nil && len(a.pt.Ranges) > 0:
// a) range from the first arg, e.g. "/tmp/www/test{0..2}{0..2}.txt" dst-bucket/www.zip
// b) from '--template'
var trimPrefix string
Expand All @@ -328,9 +328,15 @@ func putApndArchHandler(c *cli.Context) (err error) {
}
return verbRange(c, &a, a.pt, a.dst.bck, trimPrefix, a.archpath, incl)
default: // one directory
var ndir int

fobjs, err := lsFobj(c, a.src.arg, "" /*trim pref*/, a.archpath /*append pref*/, &ndir, a.src.recurs, incl)
var (
ndir int
srcpath = a.src.arg
)
if a.pt != nil {
debug.Assert(srcpath == "", srcpath)
srcpath = a.pt.Prefix
}
fobjs, err := lsFobj(c, srcpath, "" /*trim pref*/, a.archpath /*append pref*/, &ndir, a.src.recurs, incl)
if err != nil {
return err
}
Expand Down
15 changes: 11 additions & 4 deletions cmd/cli/cli/object_hdlr.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ func putHandler(c *cli.Context) error {
// a) csv of files and/or directories (names) embedded into the first arg, e.g. "f1[,f2...]" dst-bucket[/prefix]
// b) csv from '--list' flag
return verbList(c, &a, a.src.fdnames, a.dst.bck, a.dst.oname /*virt subdir*/, incl)
case a.pt != nil:
case a.pt != nil && len(a.pt.Ranges) > 0:
if ok := warnMultiSrcDstPrefix(c, &a, fmt.Sprintf("matching '%s'", a.src.tmpl)); !ok {
return nil
}
Expand All @@ -353,11 +353,18 @@ func putHandler(c *cli.Context) error {
}

// 4. directory
var ndir int
if ok := warnMultiSrcDstPrefix(c, &a, fmt.Sprintf("from '%s' directory", a.src.arg)); !ok {
var (
ndir int
srcpath = a.src.arg
)
if a.pt != nil {
debug.Assert(srcpath == "", srcpath)
srcpath = a.pt.Prefix
}
if ok := warnMultiSrcDstPrefix(c, &a, fmt.Sprintf("from '%s' directory", srcpath)); !ok {
return nil
}
fobjs, err := lsFobj(c, a.src.abspath, "", a.dst.oname, &ndir, a.src.recurs, incl)
fobjs, err := lsFobj(c, srcpath, "", a.dst.oname, &ndir, a.src.recurs, incl)
if err != nil {
return err
}
Expand Down
7 changes: 3 additions & 4 deletions cmd/cli/cli/verbfobj.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ func verbFobjs(c *cli.Context, wop wop, fobjs []fobj, bck cmn.Bck, ndir int, rec
}

var cptn string
if flagIsSet(c, dryRunFlag) {
cptn = dryRunHeader() + " "
}
cptn += fmt.Sprintf("%s %d file%s", wop.verb(), l, cos.Plural(l))
cptn += ndir2tag(ndir, recurs)
cptn += fmt.Sprintf(" => %s", wop.dest())
Expand All @@ -89,7 +86,9 @@ func verbFobjs(c *cli.Context, wop wop, fobjs []fobj, bck cmn.Bck, ndir int, rec
}

// confirm
if !flagIsSet(c, yesFlag) {
if flagIsSet(c, dryRunFlag) {
actionCptn(c, dryRunHeader()+" ", cptn)
} else if !flagIsSet(c, yesFlag) {
if ok := confirm(c, cptn+"?"); !ok {
fmt.Fprintln(c.App.Writer, "Operation canceled")
return nil
Expand Down
31 changes: 17 additions & 14 deletions cmd/cli/cli/yap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package cli

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -103,23 +104,25 @@ func (a *putargs) parse(c *cli.Context, emptyDstOnameOK bool) (err error) {
if err != nil {
return
}
// src via local filenames
if !flagIsSet(c, listFlag) && !flagIsSet(c, templateFlag) {
return fmt.Errorf("missing source arg in %q", c.Command.ArgsUsage)
}
if flagIsSet(c, listFlag) {

// source files via '--list' or '--template'
switch {
case flagIsSet(c, listFlag):
csv := parseStrFlag(c, listFlag)
a.src.fdnames = splitCsv(csv)
return
}
// optional template to select local source(s)
var pt cos.ParsedTemplate
a.src.tmpl = parseStrFlag(c, templateFlag)
pt, err = cos.NewParsedTemplate(a.src.tmpl)
if err == nil {
a.pt = &pt
return nil
case flagIsSet(c, templateFlag):
a.src.tmpl = parseStrFlag(c, templateFlag)
pt, err := cos.NewParsedTemplate(a.src.tmpl)
if err == nil {
a.pt = &pt
} else if err == cos.ErrEmptyTemplate {
err = errors.New("template to select source files cannot be empty")
}
return err
default:
return fmt.Errorf("missing source arg in %q", c.Command.ArgsUsage)
}
return

case c.NArg() == 2: // FILE|DIRECTORY|DIRECTORY/PATTERN BUCKET/[OBJECT_NAME]
a.src.arg = c.Args().Get(0) // src
Expand Down
42 changes: 37 additions & 5 deletions docs/cli/archive.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,9 @@ APPEND operation provides for appending files to existing archives (shards). As
| `--append` | add newly archived content to the destination object (\"archive\", \"shard\") that **must** exist |
| `--append-or-put` | **if** destination object (\"archive\", \"shard\") exists append to it, otherwise archive a new one |


### Example 1: add file to archive

#### step 1. archive a directory
#### step 1. create archive (by archiving a given source dir)

```console
$ ais archive put sys ais://nnn/sys.tar.lz4
Expand All @@ -117,7 +116,7 @@ APPEND 11 files (one directory, non-recursive) => ais://nnn/sys.tar.lz4? [Y/N]:
Done
```

#### step 2. add file to archive
#### step 2. add a single file to existing archive

```console
$ ais archive put README.md ais://nnn/sys.tar.lz4 --archpath=docs/README --append
Expand Down Expand Up @@ -153,7 +152,40 @@ NAME SIZE
sys.tar.lz4/docs/README 13.85KiB
```

### Example 2: add file to archive
### Example 2: use `--template` flag to add source files

Generally, the `--template` option combines (an optional) prefix and/or one or more ranges (e.g., bash brace expansions).

In this case, the template we use is a simple prefix with no ranges.

```console
$ ls -l /tmp/w
total 32
-rw-r--r-- 1 root root 14180 Dec 11 18:18 111
-rw-r--r-- 1 root root 14180 Dec 11 18:18 222

$ ais archive put ais://nnn/shard-001.tar --template /tmp/w/ --append
Files to upload:
EXTENSION COUNT SIZE
2 27.70KiB
TOTAL 2 27.70KiB
APPEND 2 files (one directory, non-recursive) => ais://nnn/shard-001.tar? [Y/N]: y
Done
$ ais ls ais://nnn/shard-001.tar --archive
NAME SIZE
shard-001.tar 37.50KiB
shard-001.tar/111 13.85KiB
shard-001.tar/222 13.85KiB
shard-001.tar/23ed44d8bf3952a35484-1.test 1.00KiB
shard-001.tar/452938788ebb87807043-4.test 1.00KiB
shard-001.tar/7925bc9b5eb1daa12ed0-2.test 1.00KiB
shard-001.tar/8264574b49bd188a4b27-0.test 1.00KiB
shard-001.tar/f1f25e52c5edd768e0ec-3.test 1.00KiB
```

### Example 3: add file to archive

In this example, we assume that `arch.tar` already exists.

```console
# contents _before_:
Expand All @@ -176,7 +208,7 @@ arch.tar 6KiB
arch.tar/obj2 1.0KiB
```

### Example 3: add file to archive
### Example 4: add file to archive

```console
# contents _before_:
Expand Down
29 changes: 29 additions & 0 deletions docs/cli/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,8 @@ subdir/README.md 11.24KiB

Preview the files that would be sent to the cluster, without actually putting them.

### Example 1

```bash
$ for d1 in {0..2}; do for d2 in {0..2}; mkdir -p ~/dir/test${d1}/dir && do echo "0" > ~/dir/test${d1}/dir/test${d2}.txt; done; done
$ ais put "~/dir/test{0..2}/dir/test{0..2}.txt" ais://mybucket --dry-run
Expand All @@ -888,6 +890,33 @@ $ ais put "~/dir/test{0..2}/dir/test{0..2}.txt" ais://mybucket --dry-run
(...)
```

### Example 2

Generally, the `--template` option combines (an optional) prefix and/or one or more ranges (e.g., bash brace expansions).

In this example, we only use the "prefix" part of the `--template` to specify source directory.

```console
$ ls -l /tmp/w
total 32
-rw-r--r-- 1 root root 14180 Dec 11 18:18 111
-rw-r--r-- 1 root root 14180 Dec 11 18:18 222

$ ais put ais://nnn/fff --template /tmp/w --dry-run
[DRY RUN] with no modifications to the cluster
Warning: 'fff' will be used as the destination name prefix for all files from '/tmp/w' directory
Proceed anyway? [Y/N]: y
Files to upload:
EXTENSION COUNT SIZE
2 27.70KiB
TOTAL 2 27.70KiB
[DRY RUN] PUT 2 files (one directory, non-recursive) => ais://nnn/fff
PUT /tmp/w/222 -> ais://nnn/fff222
PUT /tmp/w/111 -> ais://nnn/fff111
```

> Note: to PUT files into a virtual destination directory, use trailing '/', e.g.: `ais put ais://nnn/fff/ ...`
## Put multiple directories

Put multiple directories into the cluster with range syntax.
Expand Down

0 comments on commit f83bd00

Please sign in to comment.