def statbfile(repo, proto, sha): """statbfile sends '2\n' if the bfile is missing, '1\n' if it has a mismatched checksum, or '0\n' if it is in good condition""" filename = bfutil.findfile(repo, sha) if not filename: return '2\n' fd = None try: fd = open(filename, 'rb') return bfutil.hexsha1(fd) == sha and '0\n' or '1\n' finally: if fd: fd.close()
def getbfile(repo, proto, sha): """getbfile retrieves a bfile from the repository-local cache or system cache.""" filename = bfutil.findfile(repo, sha) if not filename: raise util.Abort(_('requested bfile %s not present in cache') % sha) f = open(filename, 'rb') length = os.fstat(f.fileno())[6] # since we can't set an HTTP content-length header here, and mercurial core # provides no way to give the length of a streamres (and reading the entire # file into RAM would be ill-advised), we just send the length on the first # line of the response, like the ssh proto does for string responses. def generator(): yield '%d\n' % length for chunk in f: yield chunk return wireproto.streamres(generator())
def getfilectx(repo, memctx, f): if bfutil.standin(f) in files: # if the file isn't in the manifest then it was removed # or renamed, raise IOError to indicate this try: fctx = ctx.filectx(bfutil.standin(f)) except error.LookupError: raise IOError() renamed = fctx.renamed() if renamed: renamed = bfutil.splitstandin(renamed[0]) hash = fctx.data().strip() path = bfutil.findfile(rsrc, hash) ### TODO: What if the file is not cached? data = '' fd = None try: fd = open(path, 'rb') data = fd.read() finally: if fd: fd.close() return context.memfilectx(f, data, 'l' in fctx.flags(), 'x' in fctx.flags(), renamed) else: try: fctx = ctx.filectx(f) except error.LookupError: raise IOError() renamed = fctx.renamed() if renamed: renamed = renamed[0] data = fctx.data() if f == '.hgtags': newdata = [] for line in data.splitlines(): id, name = line.split(' ', 1) newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]), name)) data = ''.join(newdata) return context.memfilectx(f, data, 'l' in fctx.flags(), 'x' in fctx.flags(), renamed)
def uploadbfiles(ui, rsrc, rdst, files): '''upload big files to the central store''' # Don't upload locally. All bfiles are in the system wide cache # so the other repo can just get them from there. if not files or rdst.local(): return store = basestore._openstore(rsrc, rdst, put=True) at = 0 for hash in files: ui.progress(_('uploading bfiles'), at, unit='bfile', total=len(files)) if store.exists(hash): at += 1 continue source = bfutil.findfile(rsrc, hash) if not source: raise util.Abort(_('Missing bfile %s needs to be uploaded') % hash) # XXX check for errors here store.put(source, hash) at += 1 ui.progress('uploading bfiles', None)
def updatebfiles(ui, repo): wlock = repo.wlock() try: bfdirstate = bfutil.openbfdirstate(ui, repo) s = bfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False, False, False) unsure, modified, added, removed, missing, unknown, ignored, clean = s bfiles = bfutil.listbfiles(repo) toget = [] at = 0 updated = 0 removed = 0 printed = False if bfiles: ui.status(_('getting changed bfiles\n')) printed = True for bfile in bfiles: at += 1 if os.path.exists(repo.wjoin(bfile)) and not \ os.path.exists(repo.wjoin(bfutil.standin(bfile))): os.unlink(repo.wjoin(bfile)) removed += 1 bfdirstate.forget(bfutil.unixpath(bfile)) continue expectedhash = repo[None][bfutil.standin(bfile)].data().strip() mode = os.stat(repo.wjoin(bfutil.standin(bfile))).st_mode if not os.path.exists(repo.wjoin(bfile)) or expectedhash != \ bfutil.hashfile(repo.wjoin(bfile)): path = bfutil.findfile(repo, expectedhash) if not path: toget.append((bfile, expectedhash)) else: util.makedirs(os.path.dirname(repo.wjoin(bfile))) shutil.copy(path, repo.wjoin(bfile)) os.chmod(repo.wjoin(bfile), mode) updated += 1 bfdirstate.normal(bfutil.unixpath(bfile)) elif os.path.exists(repo.wjoin(bfile)) and mode != \ os.stat(repo.wjoin(bfile)).st_mode: os.chmod(repo.wjoin(bfile), mode) updated += 1 bfdirstate.normal(bfutil.unixpath(bfile)) if toget: store = basestore._openstore(repo) (success, missing) = store.get(toget) else: success, missing = [],[] for (filename, hash) in success: mode = os.stat(repo.wjoin(bfutil.standin(filename))).st_mode os.chmod(repo.wjoin(filename), mode) updated += 1 bfdirstate.normal(bfutil.unixpath(filename)) for bfile in bfdirstate: if bfile not in bfiles: if os.path.exists(repo.wjoin(bfile)): if not printed: ui.status(_('getting changed bfiles\n')) printed = True os.unlink(repo.wjoin(bfile)) removed += 1 path = bfutil.unixpath(bfile) try: # Mercurial >= 1.9 bfdirstate.drop(path) except AttributeError: # Mercurial <= 1.8 bfdirstate.forget(path) bfdirstate.write() if printed: ui.status(_('%d big files updated, %d removed\n') % (updated, removed)) finally: wlock.release()
def revertbfiles(ui, repo, filelist=None): wlock = repo.wlock() try: bfdirstate = bfutil.openbfdirstate(ui, repo) s = bfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False, False, False) unsure, modified, added, removed, missing, unknown, ignored, clean = s bfiles = bfutil.listbfiles(repo) toget = [] at = 0 updated = 0 for bfile in bfiles: if filelist is None or bfile in filelist: if not os.path.exists(repo.wjoin(bfutil.standin(bfile))): bfdirstate.remove(bfile) continue if os.path.exists(repo.wjoin(bfutil.standin(os.path.join(bfile\ + '.orig')))): shutil.copyfile(repo.wjoin(bfile), repo.wjoin(bfile + \ '.orig')) at += 1 expectedhash = repo[None][bfutil.standin(bfile)].data().strip() mode = os.stat(repo.wjoin(bfutil.standin(bfile))).st_mode if not os.path.exists(repo.wjoin(bfile)) or expectedhash != \ bfutil.hashfile(repo.wjoin(bfile)): path = bfutil.findfile(repo, expectedhash) if path is None: toget.append((bfile, expectedhash)) else: util.makedirs(os.path.dirname(repo.wjoin(bfile))) shutil.copy(path, repo.wjoin(bfile)) os.chmod(repo.wjoin(bfile), mode) updated += 1 if bfutil.standin(bfile) not in repo['.']: bfdirstate.add(bfutil.unixpath(bfile)) elif expectedhash == repo['.'][bfutil.standin(bfile)] \ .data().strip(): bfdirstate.normal(bfutil.unixpath(bfile)) else: bfutil.dirstate_normaldirty(bfdirstate, bfutil.unixpath(bfile)) elif os.path.exists(repo.wjoin(bfile)) and mode != \ os.stat(repo.wjoin(bfile)).st_mode: os.chmod(repo.wjoin(bfile), mode) updated += 1 if bfutil.standin(bfile) not in repo['.']: bfdirstate.add(bfutil.unixpath(bfile)) elif expectedhash == \ repo['.'][bfutil.standin(bfile)].data().strip(): bfdirstate.normal(bfutil.unixpath(bfile)) else: bfutil.dirstate_normaldirty(bfdirstate, bfutil.unixpath(bfile)) if toget: store = basestore._openstore(repo) success, missing = store.get(toget) else: success, missing = [], [] for (filename, hash) in success: mode = os.stat(repo.wjoin(bfutil.standin(filename))).st_mode os.chmod(repo.wjoin(filename), mode) updated += 1 if bfutil.standin(filename) not in repo['.']: bfdirstate.add(bfutil.unixpath(filename)) elif hash == repo['.'][bfutil.standin(filename)].data().strip(): bfdirstate.normal(bfutil.unixpath(filename)) else: bfutil.dirstate_normaldirty(bfdirstate, bfutil.unixpath(filename)) removed = 0 for bfile in bfdirstate: if filelist is None or bfile in filelist: if not os.path.exists(repo.wjoin(bfutil.standin(bfile))): if os.path.exists(repo.wjoin(bfile)): os.unlink(repo.wjoin(bfile)) removed += 1 if bfutil.standin(bfile) in repo['.']: bfdirstate.remove(bfutil.unixpath(bfile)) else: bfdirstate.forget(bfutil.unixpath(bfile)) else: state = repo.dirstate[bfutil.standin(bfile)] if state == 'n': bfdirstate.normal(bfile) elif state == 'r': bfdirstate.remove(bfile) elif state == 'a': bfdirstate.add(bfile) elif state == '?': try: # Mercurial >= 1.9 bfdirstate.drop(bfile) except AttributeError: # Mercurial <= 1.8 bfdirstate.forget(bfile) bfdirstate.write() finally: wlock.release()