Kiln »
Unity3DUnity 3D's proposed fixes and extensions to Kiln BFiles
Alias information
is an alias for .
Mercurial and Git clients can push and pull from this alias URL to interact with this repository. You can change to which repository an alias points by going to the Aliases link on the project page.
Fix problem where current working directory can be nonsense if function called outside repo dir. This is necessary for the MonoDevelop plugin for mercurial/kbfiles.
'''bfiles utility code: must not import other modules in this package.'''importosimporterrnoimportinspectimportshutilimportstatfrommercurialimport \
util,dirstate,cmdutil,matchasmatch_frommercurial.i18nimport_short_name='.kbf'long_name='kilnbfiles'# -- Portability wrappers ----------------------------------------------if'subrepos'ininspect.getargspec(dirstate.dirstate.status)[0]:# for Mercurial >= 1.5defdirstate_walk(dirstate,matcher,unknown=False,ignored=False):returndirstate.walk(matcher,[],unknown,ignored)else:# for Mercurial <= 1.4defdirstate_walk(dirstate,matcher,unknown=False,ignored=False):returndirstate.walk(matcher,unknown,ignored)defrepo_add(repo,list):try:# Mercurial <= 1.5add=repo.addexceptAttributeError:# Mercurial >= 1.6add=repo[None].addreturnadd(list)defrepo_remove(repo,list,unlink=False):try:# Mercurial <= 1.5remove=repo.removeexceptAttributeError:# Mercurial >= 1.6remove=repo[None].removereturnremove(list,unlink=unlink)defrepo_forget(repo,list):try:# Mercurial <= 1.5forget=repo.forgetexceptAttributeError:# Mercurial >= 1.6forget=repo[None].forgetreturnforget(list)defdirstate_normaldirty(dirstate,file):try:normaldirty=dirstate.normaldirtyexceptAttributeError:# Mercurial >= 1.6: HAAAACK: I should not be using normaldirty()# (now called otherparent()), and dirstate in 1.6 prevents me# from doing so. So reimplement it here until I figure out the# right fix.defnormaldirty(f):dirstate._dirty=Truedirstate._addpath(f)dirstate._map[f]=('n',0,-2,-1)iffindirstate._copymap:deldirstate._copymap[f]normaldirty(file)deffindoutgoing(repo,remote,force):# First attempt is for Mercurial <= 1.5 second is for >= 1.6try:returnrepo.findoutgoing(remote)exceptAttributeError:frommercurialimportdiscoveryreturndiscovery.findoutgoing(repo,remote,force=force)# -- Private worker functions ------------------------------------------ifos.name=='nt':frommercurialimportwin32linkfn=win32.os_linkelse:linkfn=os.linkdeflink(src,dest):try:linkfn(src,dest)exceptOSError:# If hardlinks fail fall back on copyshutil.copyfile(src,dest)os.chmod(dest,os.stat(src).st_mode)defsystem_cache_path(ui,hash):path=ui.config(long_name,'systemcache',None)ifpath:path=os.path.join(path,hash)else:ifos.name=='nt':path=os.path.join(os.getenv('LOCALAPPDATA')oros.getenv('APPDATA'),long_name,hash)elifos.name=='posix':path=os.path.join(os.getenv('HOME'),'.'+long_name,hash)else:raiseutil.Abort(_('Unknown operating system: %s\n')%os.name)returnpathdefin_system_cache(ui,hash):returnos.path.exists(system_cache_path(ui,hash))deffind_file(repo,hash):ifin_cache(repo,hash):repo.ui.note(_('Found %s in cache\n')%hash)returncache_path(repo,hash)ifin_system_cache(repo.ui,hash):repo.ui.note(_('Found %s in system cache\n')%hash)returnsystem_cache_path(repo.ui,hash)returnNonedefopen_bfdirstate(ui,repo):''' Return a dirstate object that tracks big files: i.e. its root is the repo root, but it is saved in .hg/bfiles/dirstate. '''admin=repo.join(long_name)opener=util.opener(admin)ifhasattr(repo.dirstate,'_validate'):bfdirstate=dirstate.dirstate(opener,ui,repo.root,repo.dirstate._validate)else:bfdirstate=dirstate.dirstate(opener,ui,repo.root)# If the bfiles dirstate does not exist, populate and create it. This# ensures that we create it on the first meaningful bfiles operation in# a new clone. It also gives us an easy way to forcibly rebuild bfiles# state:# rm .hg/bfiles/dirstate && hg bfstatus# Or even, if things are really messed up:# rm -rf .hg/bfiles && hg bfstatus# (although that can lose data, e.g. pending big file revisions in# .hg/bfiles/{pending,committed}).ifnotos.path.exists(os.path.join(admin,'dirstate')):util.makedirs(admin)matcher=get_standin_matcher(repo)forstandinindirstate_walk(repo.dirstate,matcher):bigfile=split_standin(standin)hash=read_standin(repo,standin)try:curhash=hashfile(bigfile)exceptIOError,err:iferr.errno==errno.ENOENT:dirstate_normaldirty(bfdirstate,bigfile)else:raiseelse:ifcurhash==hash:bfdirstate.normal(unixpath(bigfile))else:dirstate_normaldirty(bfdirstate,bigfile)bfdirstate.write()returnbfdirstatedefbfdirstate_status(bfdirstate,repo,rev):wlock=repo.wlock()try:match=match_.always(repo.root,repo.getcwd())s=bfdirstate.status(match,[],False,False,False)(unsure,modified,added,removed,missing,unknown,ignored,clean)=sforbfileinunsure:ifrepo[rev][standin(bfile)].data().strip()!=hashfile(repo.wjoin(bfile)):modified.append(bfile)else:clean.append(bfile)bfdirstate.normal(unixpath(bfile))bfdirstate.write()finally:wlock.release()return(modified,added,removed,missing,unknown,ignored,clean)deflist_bfiles(repo,rev=None,matcher=None):'''list big files in the working copy or specified changeset'''ifmatcherisNone:matcher=get_standin_matcher(repo)bfiles=[]ifrev:cctx=repo[rev]forstandinincctx.walk(matcher):filename=split_standin(standin)bfiles.append(filename)else:forstandininsorted(dirstate_walk(repo.dirstate,matcher)):filename=split_standin(standin)bfiles.append(filename)returnbfilesdefin_cache(repo,hash):returnos.path.exists(cache_path(repo,hash))defcreate_dir(dir):ifnotos.path.exists(dir):os.makedirs(dir)defcache_path(repo,hash):returnrepo.join(os.path.join(long_name,hash))defcopy_to_cache(repo,rev,file,uploaded=False):hash=read_standin(repo,standin(file))ifin_cache(repo,hash):returncreate_dir(os.path.dirname(cache_path(repo,hash)))ifin_system_cache(repo.ui,hash):link(system_cache_path(repo.ui,hash),cache_path(repo,hash))else:shutil.copyfile(repo.wjoin(file),cache_path(repo,hash))os.chmod(cache_path(repo,hash),os.stat(repo.wjoin(file)).st_mode)create_dir(os.path.dirname(system_cache_path(repo.ui,hash)))link(cache_path(repo,hash),system_cache_path(repo.ui,hash))defget_standin_matcher(repo,pats=[],opts={}):'''Return a match object that applies pats to <repo>/.kbf.'''standin_dir=repo.pathto(short_name) if pats:
# patterns supplied: search .hgbfiles relative to current dir
cwd = repo.getcwd()
+ if (os.path.isabs(cwd)):+ # This means that the cwd is outside the repo.+ # Pass repo-relative path instead.+ cwd = '' pats = [os.path.join(standin_dir, cwd, pat) for pat in pats]
elif os.path.isdir(standin_dir):
# no patterns: relative to repo root
pats=[standin_dir]else:# no patterns and no .hgbfiles dir: return matcher that matches nothingmatch=match_.match(repo.root,None,[],exact=True)match.matchfn=lambdaf:Falsereturnmatchreturnget_matcher(repo,pats,opts,showbad=False)defget_matcher(repo,pats=[],opts={},showbad=True):'''Wrapper around cmdutil.match() that adds showbad: if false, neuter the match object\'s bad() method so it does not print any warnings about missing files or directories.'''match=cmdutil.match(repo,pats,opts)ifnotshowbad:match.bad=lambdaf,msg:Nonereturnmatchdefcompose_standin_matcher(repo,rmatcher):'''Return a matcher that accepts standins corresponding to the files accepted by rmatcher. Pass the list of files in the matcher as the paths specified by the user.'''smatcher=get_standin_matcher(repo,rmatcher.files())isstandin=smatcher.matchfndefcomposed_matchfn(f):returnisstandin(f)andrmatcher.matchfn(split_standin(f))smatcher.matchfn=composed_matchfnreturnsmatcherdefstandin(filename):'''Return the repo-relative path to the standin for the specified big file.'''# Notes:# 1) Most callers want an absolute path, but _create_standin() needs# it repo-relative so bfadd() can pass it to repo_add(). So leave# it up to the caller to use repo.wjoin() to get an absolute path.# 2) Join with '/' because that's what dirstate always uses, even on# Windows. Change existing separator to '/' first in case we are# passed filenames from an external source (like the command line).returnshort_name+'/'+filename.replace(os.sep,'/')defis_standin(filename):'''Return true if filename is a big file standin. filename must be in Mercurial\'s internal form (slash-separated).'''returnfilename.startswith(short_name+'/')defsplit_standin(filename):# Split on / because that's what dirstate always uses, even on Windows.# Change local separator to / first just in case we are passed filenames# from an external source (like the command line).bits=filename.replace(os.sep,'/').split('/',1)iflen(bits)==2andbits[0]==short_name:returnbits[1]else:returnNonedefupdate_standin(repo,standin):file=repo.wjoin(split_standin(standin))if(os.path.exists(file)):hash=hashfile(file)executable=get_executable(file)write_standin(repo,standin,hash,executable)defread_standin(repo,standin):'''read hex hash from <repo.root>/<standin>'''returnread_hash(repo.wjoin(standin))defwrite_standin(repo,standin,hash,executable):'''write hhash to <repo.root>/<standin>'''write_hash(hash,repo.wjoin(standin),executable)defcopy_and_hash(instream,outfile):'''Read bytes from instream (iterable) and write them to outfile, computing the SHA-1 hash of the data along the way. Close outfile when done and return the binary hash.'''hasher=util.sha1('')fordataininstream:hasher.update(data)outfile.write(data)# Blecch: closing a file that somebody else opened is rude and# wrong. But it's so darn convenient and practical! After all,# outfile was opened just to copy and hash.outfile.close()returnhasher.digest()defhashrepofile(repo,file):returnhashfile(repo.wjoin(file))defhashfile(file):ifnotos.path.exists(file):return'';hasher=util.sha1('')withopen(file,'rb')asfd:fordatainblockstream(fd):hasher.update(data)returnhasher.hexdigest()defblockstream(infile,blocksize=128*1024):"""Generator that yields blocks of data from infile and closes infile."""whileTrue:data=infile.read(blocksize)ifnotdata:breakyielddata# Same blecch as above.infile.close()defread_hash(filename):rfile=open(filename,'rb')hash=rfile.read(40)rfile.close()iflen(hash)<40:raiseutil.Abort(_('bad hash in \'%s\' (only %d bytes long)')%(filename,len(hash)))returnhashdefwrite_hash(hash,filename,executable):util.makedirs(os.path.dirname(filename))ifos.path.exists(filename):os.unlink(filename)ifos.name=='posix':# Yuck: on Unix, go through open(2) to ensure that the caller's mode is# filtered by umask() in the kernel, where it's supposed to be done.wfile=os.fdopen(os.open(filename,os.O_WRONLY|os.O_CREAT,get_mode(executable)),'wb')else:# But on Windows, use open() directly, since passing mode='wb' to os.fdopen()# does not work. (Python bug?)wfile=open(filename,'wb')try:wfile.write(hash)wfile.write('\n')finally:wfile.close()defget_executable(filename):mode=os.stat(filename).st_modereturn(mode&stat.S_IXUSR)and(mode&stat.S_IXGRP)and(mode&stat.S_IXOTH)defget_mode(executable):ifexecutable:return0755else:return0644defurljoin(first,second,*arg):defjoin(left,right):ifnotleft.endswith('/'):left+='/'ifright.startswith('/'):right=right[1:]returnleft+righturl=join(first,second)forainarg:url=join(url,a)returnurl# Convert a path to a unix style path. This is used to give a# canonical path to the bfdirstate.defunixpath(path):returnos.path.normpath(path).replace(os.sep,'/')
Attach a Trello Card
Add a tag
Your session has expired
You are no longer logged in. Please log in and try your request again.
Filter RSS Feed
This RSS feed URL allows you to see the contents of your current filter using any feed reader.
This link includes a special authentication token. If you share the URL with anyone else, they can see this RSS feed's activity. You can disable these tokens when needed.
Your current filter is unsaved; changing it won't affect this RSS feed.