fdatasync,
hostname, localtime, log, merge_iter,
mmap_read, mmap_readwrite,
- progress, qprogress, unlink, username, userfullname,
+ progress, qprogress, stat_if_exists,
+ unlink, username, userfullname,
utc_offset_str)
self._require_objcache()
return self.objcache.exists(id, want_source=want_source)
- def write(self, sha, type, content):
- """Write an object to the pack file. Fails if sha exists()."""
+ def just_write(self, sha, type, content):
+ """Write an object to the pack file, bypassing the objcache. Fails if
+ sha exists()."""
self._write(sha, type, content)
def maybe_write(self, type, content):
"""Write an object to the pack file if not present and return its id."""
sha = calc_hash(type, content)
if not self.exists(sha):
- self.write(sha, type, content)
+ self.just_write(sha, type, content)
self._require_objcache()
self.objcache.add(sha)
return sha
return env
-def list_refs(refname=None, repo_dir=None,
+def list_refs(refnames=None, repo_dir=None,
limit_to_heads=False, limit_to_tags=False):
- """Yield (refname, hash) tuples for all repository refs unless a ref
- name is specified. Given a ref name, only include tuples for that
- particular ref. The limits restrict the result items to
- refs/heads or refs/tags. If both limits are specified, items from
- both sources will be included.
+ """Yield (refname, hash) tuples for all repository refs unless
+ refnames are specified. In that case, only include tuples for
+ those refs. The limits restrict the result items to refs/heads or
+ refs/tags. If both limits are specified, items from both sources
+ will be included.
"""
argv = ['git', 'show-ref']
if limit_to_tags:
argv.append('--tags')
argv.append('--')
- if refname:
- argv += [refname]
+ if refnames:
+ argv += refnames
p = subprocess.Popen(argv,
preexec_fn = _gitenv(repo_dir),
stdout = subprocess.PIPE)
def read_ref(refname, repo_dir = None):
"""Get the commit id of the most recent commit made on a given ref."""
- refs = list_refs(refname, repo_dir=repo_dir, limit_to_heads=True)
+ refs = list_refs(refnames=[refname], repo_dir=repo_dir, limit_to_heads=True)
l = tuple(islice(refs, 2))
if l:
assert(len(l) == 1)
def check_repo_or_die(path=None):
- """Make sure a bup repository exists, and abort if not.
- If the path to a particular repository was not specified, this function
- initializes the default repository automatically.
- """
+ """Check to see if a bup repository probably exists, and abort if not."""
guess_repo(path)
- try:
- os.stat(repo('objects/pack/.'))
- except OSError as e:
- if e.errno == errno.ENOENT:
- log('error: %r is not a bup repository; run "bup init"\n'
- % repo())
+ top = repo()
+ pst = stat_if_exists(top + '/objects/pack')
+ if pst and stat.S_ISDIR(pst.st_mode):
+ return
+ if not pst:
+ top_st = stat_if_exists(top)
+ if not top_st:
+ log('error: repository %r does not exist (see "bup help init")\n'
+ % top)
sys.exit(15)
- else:
- log('error: %s\n' % e)
- sys.exit(14)
+ log('error: %r is not a repository\n' % top)
+ sys.exit(14)
_ver = None
self.p = None
self.inprogress = None
- def _restart(self):
+ def restart(self):
self._abort()
self.p = subprocess.Popen(['git', 'cat-file', '--batch'],
stdin=subprocess.PIPE,
def _fast_get(self, id):
if not self.p or self.p.poll() != None:
- self._restart()
+ self.restart()
assert(self.p)
poll_result = self.p.poll()
assert(poll_result == None)
include_data=None):
"""Yield everything reachable from id via cat_pipe as a WalkItem,
stopping whenever stop_at(id) returns true. Throw MissingObject
- if a hash encountered is missing from the repository.
-
+ if a hash encountered is missing from the repository, and don't
+ read or return blob content in the data field unless include_data
+ is set.
"""
# Maintain the pending stack on the heap to avoid stack overflow
pending = [(id, [], [], None)]
if stop_at and stop_at(id):
continue
- item_it = cat_pipe.get(id) # FIXME: use include_data
+ if (not include_data) and mode and stat.S_ISREG(mode):
+ # If the object is a "regular file", then it's a leaf in
+ # the graph, so we can skip reading the data if the caller
+ # hasn't requested it.
+ yield WalkItem(id=id, type='blob',
+ chunk_path=chunk_path, path=parent_path,
+ mode=mode,
+ data=None)
+ continue
+
+ item_it = cat_pipe.get(id)
type = item_it.next()
if type not in ('blob', 'commit', 'tree'):
raise Exception('unexpected repository object type %r' % type)