The following commands are available inside `bup ftp`:
-ls [-a]
-: print the contents of the current working directory.
+ls [-s] [-a] [*path*]
+: print the contents of a directory. If no path argument
+ is given, the current directory's contents are listed.
If -a is given, also include hidden files (files which
- start with a `.` character).
+ start with a `.` character). If -s is given, each file
+ is displayed with its hash from the bup archive to its
+ left.
cd *dirname*
: change to a different working directory
of the backup, and subsequent levels correspond to files in
the backup.
+When `bup ls` is asked to output on a tty, it formats its output
+in columns so that it can list as much as possible in as few lines
+as possible. However, when `bup ls` is asked to output to something
+other than a tty (say you pipe the output to another command, or you
+redirect it to a file), it will output one file name per line. This
+makes the listing easier to parse with external tools.
+
Note that `bup ls` doesn't show hidden files by default and one needs to use
the `-a` option to show them. Files are hidden when their name begins with a
dot. For example, on the topmost level, the special directories named `.commit`
Getting started
----------------
+===============
+
+
+From source
+-----------
- Check out the bup source code using git:
(The tests should pass. If they don't pass for you, stop here and send
me an email.)
-
+
+
+From binary packages
+--------------------
+
+Binary packages of bup are known to be built for the following OSes:
+
+ - Debian:
+ http://packages.debian.org/search?searchon=names&keywords=bup
+ - Ubuntu:
+ http://packages.ubuntu.com/search?searchon=names&keywords=bup
+ - NetBSD
+
+
+Using bup
+---------
+
- Try making a local backup as a tar file:
tar -cvf - /etc | bup split -n local-etc -vv
Notes on FreeBSD
-================
+----------------
- FreeBSD's default 'make' command doesn't like bup's Makefile. In order to
compile the code, run tests and install bup, you need to install GNU Make
How it works
-------------
+============
Basic storage:
How you can help
-----------------
+================
bup is a work in progress and there are many ways it can still be improved.
If you'd like to contribute patches, ideas, or bug reports, please join the
#!/usr/bin/env python
import sys, os, stat, fnmatch
-from bup import options, git, shquote, vfs
+from bup import options, git, shquote, vfs, ls
from bup.helpers import *
handle_ctrl_c()
-def node_name(text, n):
- if stat.S_ISDIR(n.mode):
- return '%s/' % text
- elif stat.S_ISLNK(n.mode):
- return '%s@' % text
- else:
- return '%s' % text
-
-
class OptionError(Exception):
pass
-ls_optspec = """
-ls [-a] [path...]
---
-a,all include hidden files in the listing
-"""
-ls_opt = options.Options(ls_optspec, onabort=OptionError)
-
+# Check out lib/bup/ls.py for the opt spec
def do_ls(cmd_args):
try:
- (opt, flags, extra) = ls_opt.parse(cmd_args)
+ ls.do_ls(cmd_args, pwd, onabort=OptionError)
except OptionError, e:
return
- L = []
-
- for path in (extra or ['.']):
- n = pwd.try_resolve(path)
-
- if stat.S_ISDIR(n.mode):
- for sub in n:
- name = sub.name
- if opt.all or not len(name)>1 or not name.startswith('.'):
- L.append(node_name(name, sub))
- else:
- L.append(node_name(path, n))
- print columnate(L, '')
-
def write_to_file(inf, outf):
for blob in chunkyreader(inf):
try:
yield raw_input('bup> ')
except EOFError:
+ print '' # Clear the line for the terminal's next prompt
break
else:
for line in sys.stdin:
#!/usr/bin/env python
-import sys, stat
-from bup import options, git, vfs
+import sys
+from bup import git, vfs, ls
from bup.helpers import *
-def print_node(text, n):
- prefix = ''
- if opt.hash:
- prefix += "%s " % n.hash.encode('hex')
- if stat.S_ISDIR(n.mode):
- print '%s%s/' % (prefix, text)
- elif stat.S_ISLNK(n.mode):
- print '%s%s@' % (prefix, text)
- else:
- print '%s%s' % (prefix, text)
-
-
-optspec = """
-bup ls <dirs...>
---
-s,hash show hash for each file
-a,all show hidden files
-"""
-o = options.Options(optspec)
-(opt, flags, extra) = o.parse(sys.argv[1:])
git.check_repo_or_die()
top = vfs.RefList(None)
-if not extra:
- extra = ['/']
-
-ret = 0
-for d in extra:
- try:
- n = top.lresolve(d)
- if stat.S_ISDIR(n.mode):
- for sub in n:
- if opt.all or not sub.name.startswith('.'):
- print_node(sub.name, sub)
- else:
- if opt.all or not n.name.startswith('.'):
- print_node(d, n)
- except vfs.NodeError, e:
- log('error: %s\n' % e)
- ret = 1
+# Check out lib/bup/ls.py for the opt spec
+ret = ls.do_ls(sys.argv[1:], top, default='/', spec_prefix='bup ')
sys.exit(ret)
except OSError, e:
if e.errno == errno.ENOENT:
if repodir != home_repodir:
- log('error: %r is not a bup/git repository\n' % repo())
+ log('error: %r is not a bup repository; run "bup init"\n'
+ % repo())
sys.exit(15)
else:
init_repo()
--- /dev/null
+"""Common code for listing files from a bup repository."""
+import stat
+from bup import options, vfs
+from helpers import *
+
+
+def node_name(text, n, show_hash):
+ """Add symbols to a node's name to differentiate file types."""
+ prefix = ''
+ if show_hash:
+ prefix += "%s " % n.hash.encode('hex')
+ if stat.S_ISDIR(n.mode):
+ return '%s%s/' % (prefix, text)
+ elif stat.S_ISLNK(n.mode):
+ return '%s%s@' % (prefix, text)
+ else:
+ return '%s%s' % (prefix, text)
+
+
+optspec = """
+%sls [-a] [path...]
+--
+s,hash show hash for each file
+a,all show hidden files
+"""
+
+def do_ls(args, pwd, default='.', onabort=None, spec_prefix=''):
+ """Output a listing of a file or directory in the bup repository.
+
+ When stdout is attached to a tty, the output is formatted in columns. When
+ not attached to tty (for example when the output is piped to another
+ command), one file is listed per line.
+ """
+ if onabort:
+ o = options.Options(optspec % spec_prefix, onabort=onabort)
+ else:
+ o = options.Options(optspec % spec_prefix)
+ (opt, flags, extra) = o.parse(args)
+
+ L = []
+
+ ret = 0
+ for path in (extra or [default]):
+ try:
+ n = pwd.try_resolve(path)
+
+ if stat.S_ISDIR(n.mode):
+ for sub in n:
+ name = sub.name
+ if opt.all or not len(name)>1 or not name.startswith('.'):
+ if istty1:
+ L.append(node_name(name, sub, opt.hash))
+ else:
+ print node_name(name, sub, opt.hash)
+ else:
+ if istty1:
+ L.append(node_name(path, n, opt.hash))
+ else:
+ print node_name(path, n, opt.hash)
+ except vfs.NodeError, e:
+ log('error: %s\n' % e)
+ ret = 1
+
+ if istty1:
+ sys.stdout.write(columnate(L, ''))
+
+ return ret