def checkreadonly(ui, repo, op): try: reporeason = repo.vfs.read('readonlyreason') ui.warn(_('repository is read only\n')) if reporeason: ui.warn(reporeason.strip() + '\n') ui.warn(_('refusing to %s\n') % op) return True except IOError as e: if e.errno != errno.ENOENT: raise # Repo local file does not exist. Check global file. rf = ui.config('readonly', 'globalreasonfile') if rf: try: with util.posixfile(rf, 'rb') as fh: globalreason = fh.read() ui.warn(_('all repositories currently read only\n')) if globalreason: ui.warn(globalreason.strip() + '\n') ui.warn(_('refusing to %s\n') % op) return True except IOError as e: if e.errno != errno.ENOENT: raise return False
def setfile(self, fname, data): if fname in self._popped: raise EditingError('trying to set a popped file %s' % fname) if fname in self._data: self._size -= len(self._data[fname]) del self._data[fname] if fname in self._files: del self._files[fname] if self._maxsize < 0 or (len(data) + self._size) <= self._maxsize: self._data[fname] = data self._size += len(data) else: if self._tempdir is None: self._tempdir = tempfile.mkdtemp(prefix='hg-subversion-') # Avoid filename issues with these simple names fn = str(self._created) fp = hgutil.posixfile(os.path.join(self._tempdir, fn), 'wb') try: fp.write(data) finally: fp.close() self._created += 1 self._files[fname] = fn
def _generateoutputparts(head, bundlerepo, bundleroots, bundlefile): '''generates bundle that will be send to the user returns tuple with raw bundle string and bundle type ''' parts = [] if not _needsrebundling(head, bundlerepo): with util.posixfile(bundlefile, "rb") as f: unbundler = exchange.readbundle(bundlerepo.ui, f, bundlefile) if isinstance(unbundler, changegroup.cg1unpacker): part = bundle2.bundlepart('changegroup', data=unbundler._stream.read()) part.addparam('version', '01') parts.append(part) elif isinstance(unbundler, bundle2.unbundle20): haschangegroup = False for part in unbundler.iterparts(): if part.type == 'changegroup': haschangegroup = True newpart = bundle2.bundlepart(part.type, data=part.read()) for key, value in part.params.iteritems(): newpart.addparam(key, value) parts.append(newpart) if not haschangegroup: raise error.Abort( 'unexpected bundle without changegroup part, ' + 'head: %s' % hex(head), hint='report to administrator') else: raise error.Abort('unknown bundle type') else: parts = _rebundle(bundlerepo, bundleroots, head) return parts
def _readini(self): """Create iniparse object by reading every file""" if len(self._readfiles) > 1: raise NotImplementedError("wconfig does not support read() more than once") def newini(fp=None): # TODO: optionxformvalue isn't used by INIConfig ? return INIConfig(fp=fp, optionxformvalue=None) if not self._readfiles: return newini() path, fp, sections, remap = self._readfiles[0] if sections: raise NotImplementedError("wconfig does not support 'sections'") if remap: raise NotImplementedError("wconfig does not support 'remap'") if fp: fp.seek(0) return newini(fp) else: fp = util.posixfile(path, 'rb') try: return newini(fp) finally: fp.close()
def _import(ui, repo, files, opts, force=False): with repo.wlock(): # load union of current active profile revs = [repo.changelog.rev(node) for node in repo.dirstate.parents() if node != nullid] # read current configuration raw = '' if repo.vfs.exists('sparse'): raw = repo.vfs.read('sparse') oincludes, oexcludes, oprofiles = repo.readsparseconfig(raw) includes, excludes, profiles = map( set, (oincludes, oexcludes, oprofiles)) # all active rules aincludes, aexcludes, aprofiles = set(), set(), set() for rev in revs: rincludes, rexcludes, rprofiles = repo.getsparsepatterns(rev) aincludes.update(rincludes) aexcludes.update(rexcludes) aprofiles.update(rprofiles) # import rules on top; only take in rules that are not yet # part of the active rules. changed = False for file in files: with util.posixfile(util.expandpath(file)) as importfile: iincludes, iexcludes, iprofiles = repo.readsparseconfig( importfile.read()) oldsize = len(includes) + len(excludes) + len(profiles) includes.update(iincludes - aincludes) excludes.update(iexcludes - aexcludes) profiles.update(set(iprofiles) - aprofiles) if len(includes) + len(excludes) + len(profiles) > oldsize: changed = True profilecount = includecount = excludecount = 0 fcounts = (0, 0, 0) if changed: profilecount = len(profiles - aprofiles) includecount = len(includes - aincludes) excludecount = len(excludes - aexcludes) oldstatus = repo.status() oldsparsematch = repo.sparsematch() repo.writesparseconfig(includes, excludes, profiles) try: fcounts = map( len, _refresh(ui, repo, oldstatus, oldsparsematch, force)) except Exception: repo.writesparseconfig(oincludes, oexcludes, oprofiles) raise _verbose_output(ui, opts, profilecount, includecount, excludecount, *fcounts)
def getfile(self, fname): if fname in self._popped: raise EditingError('trying to get a popped file %s' % fname) if fname in self._data: return self._data[fname] if self._tempdir is None or fname not in self._files: raise IOError path = os.path.join(self._tempdir, self._files[fname]) fp = hgutil.posixfile(path, 'rb') try: return fp.read() finally: fp.close()
def writefile(path, content, readonly=False): dirname, filename = os.path.split(path) if not os.path.exists(dirname): try: os.makedirs(dirname) except OSError as ex: if ex.errno != errno.EEXIST: raise fd, temp = tempfile.mkstemp(prefix='.%s-' % filename, dir=dirname) os.close(fd) try: f = util.posixfile(temp, 'wb') f.write(content) f.close() if readonly: mode = 0o444 else: # tempfiles are created with 0o600, so we need to manually set the # mode. oldumask = os.umask(0) # there's no way to get the umask without modifying it, so set it # back os.umask(oldumask) mode = ~oldumask renamefile(temp, path) os.chmod(path, mode) except Exception: try: unlinkfile(temp) except OSError: pass raise
def _readStatus(self, ctx, ctx2, wfile, status, changeselect, force): def getstatus(repo, n1, n2, wfile): m = match.exact(repo.root, repo.getcwd(), [wfile]) modified, added, removed = repo.status(n1, n2, match=m)[:3] if wfile in modified: return 'M' if wfile in added: return 'A' if wfile in removed: return 'R' if wfile in ctx: return 'C' return None isbfile = False repo = ctx._repo maxdiff = repo.maxdiff self.flabel = u'<b>%s</b>' % self.filePath() if ctx2: # If a revision to compare to was provided, we must put it in # the context of the subrepo as well if ctx2._repo.root != ctx._repo.root: wsub2, wfileinsub2, sctx2 = \ hglib.getDeepestSubrepoContainingFile(wfile, ctx2) if wsub2: ctx2 = sctx2 absfile = repo.wjoin(wfile) if (wfile in ctx and 'l' in ctx.flags(wfile)) or \ os.path.islink(absfile): if wfile in ctx: data = ctx[wfile].data() else: data = os.readlink(absfile) self.contents = data self.flabel += _(' <i>(is a symlink)</i>') return if ctx2 is None: ctx2 = ctx.p1() if status is None: status = getstatus(repo, ctx2.node(), ctx.node(), wfile) mde = _('File or diffs not displayed: ' 'File is larger than the specified max size.\n' 'maxdiff = %s KB') % (maxdiff // 1024) if status in ('R', '!'): if wfile in ctx.p1(): fctx = ctx.p1()[wfile] if fctx._filelog.rawsize(fctx.filerev()) > maxdiff: self.error = mde else: olddata = fctx.data() if '\0' in olddata: self.error = 'binary file' else: self.contents = olddata self.flabel += _(' <i>(was deleted)</i>') elif hasattr(ctx.p1(), 'hasStandin') and ctx.p1().hasStandin(wfile): self.error = 'binary file' self.flabel += _(' <i>(was deleted)</i>') else: self.flabel += _(' <i>(was added, now missing)</i>') return if status in ('I', '?'): assert ctx.rev() is None self.flabel += _(' <i>(is unversioned)</i>') if os.path.getsize(absfile) > maxdiff: self.error = mde return data = util.posixfile(absfile, 'r').read() if not force and '\0' in data: self.error = 'binary file' else: self.contents = data return if status in ('M', 'A', 'C'): if ctx.hasStandin(wfile): wfile = ctx.findStandin(wfile) isbfile = True try: fctx, newdata = self._checkMaxDiff(ctx, wfile, maxdiff, force) except _BadContent: if status == 'A': self._checkRenamed(repo, ctx, ctx2, wfile) raise self.contents = newdata if status == 'C': # no further comparison is necessary return for pctx in ctx.parents(): if 'x' in fctx.flags() and 'x' not in pctx.flags(wfile): self.elabel = _("exec mode has been " "<font color='red'>set</font>") elif 'x' not in fctx.flags() and 'x' in pctx.flags(wfile): self.elabel = _("exec mode has been " "<font color='red'>unset</font>") if status == 'A': oldname = self._checkRenamed(repo, ctx, ctx2, wfile) if not oldname: return olddata = ctx2[oldname].data() elif status == 'M': if wfile not in ctx2: # merge situation where file was added in other branch self.flabel += _(' <i>(was added)</i>') return oldname = wfile olddata = ctx2[wfile].data() else: return self.olddata = olddata if changeselect: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = True m = match.exact(repo.root, repo.root, [wfile]) fp = cStringIO.StringIO() copy = {} if oldname != wfile: copy[wfile] = oldname patches = patch.diff(repo, ctx.node(), None, match=m, opts=diffopts, copy=copy) for c in patches: fp.write(c) fp.seek(0) # feed diffs through parsepatch() for more fine grained # chunk selection filediffs = patch.parsepatch(fp) if filediffs and filediffs[0].hunks: self.changes = filediffs[0] else: self.diff = '' return self.changes.excludecount = 0 values = [] lines = 0 for chunk in self.changes.hunks: buf = cStringIO.StringIO() chunk.write(buf) chunk.excluded = False val = buf.getvalue() values.append(val) chunk.lineno = lines chunk.linecount = len(val.splitlines()) lines += chunk.linecount self.diff = ''.join(values) else: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = False newdate = util.datestr(ctx.date()) olddate = util.datestr(ctx2.date()) if isbfile: olddata += '\0' newdata += '\0' difftext = hglib.unidifftext(olddata, olddate, newdata, newdate, oldname, wfile, opts=diffopts) if difftext: self.diff = ('diff -r %s -r %s %s\n' % (ctx, ctx2, oldname) + difftext) else: self.diff = ''
'hasStandin') and ctx.p1().hasStandin(wfile): self.error = 'binary file' self.flabel += _(' <i>(was deleted)</i>') else: self.flabel += _(' <i>(was added, now missing)</i>') return if status in ('I', '?', 'C'): if ctx.rev() is None: if status in ('I', '?'): self.flabel += _(' <i>(is unversioned)</i>') if os.path.getsize(absfile) > maxdiff: self.error = mde return else: data = util.posixfile(absfile, 'r').read() elif ctx.hasStandin(wfile): data = '\0' else: data = ctx.filectx(wfile).data() if '\0' in data: self.error = 'binary file' else: self.contents = data return if status in ('M', 'A'): if ctx.hasStandin(wfile): wfile = ctx.findStandin(wfile) isbfile = True res = self.checkMaxDiff(ctx, wfile, maxdiff, status)
raise error.ParseError(err.message.splitlines()[0], loc) if not self._readfiles: return newini() path, fp, sections, remap = self._readfiles[0] if sections: raise NotImplementedError("wconfig does not support 'sections'") if remap: raise NotImplementedError("wconfig does not support 'remap'") if fp: fp.seek(0) return newini(fp) else: fp = util.posixfile(path, 'rb') try: return newini(fp) finally: fp.close() def _replaylogs(self, ini): def getsection(ini, section): if section in ini: return ini[section] else: newns = getattr(ini, '_new_namespace', getattr(ini, 'new_namespace')) return newns(section) for k, v in self._sections.iteritems():
elif hasattr(ctx.p1(), 'hasStandin') and ctx.p1().hasStandin(wfile): self.error = 'binary file' self.flabel += _(' <i>(was deleted)</i>') else: self.flabel += _(' <i>(was added, now missing)</i>') return if status in ('I', '?', 'C'): if ctx.rev() is None: if status in ('I', '?'): self.flabel += _(' <i>(is unversioned)</i>') if os.path.getsize(absfile) > maxdiff: self.error = mde return else: data = util.posixfile(absfile, 'r').read() elif ctx.hasStandin(wfile): data = '\0' else: data = ctx.filectx(wfile).data() if not force and '\0' in data: self.error = 'binary file' else: self.contents = data return if status in ('M', 'A'): if ctx.hasStandin(wfile): wfile = ctx.findStandin(wfile) isbfile = True res = self.checkMaxDiff(ctx, wfile, maxdiff, status, force)
class _wconfig(object): """Wrapper for config.config to replay changes to iniparse on write This records set/del operations and replays them on write(). Source file is reloaded before replaying changes, so that it doesn't override changes for another part of file made by somebody else: - A "set foo = bar", B "set baz = bax" => "foo = bar, baz = bax" - A "set foo = bar", B "set foo = baz" => "foo = baz" (last one wins) - A "del foo", B "set foo = baz" => "foo = baz" (last one wins) - A "set foo = bar", B "del foo" => "" (last one wins) """ def __init__(self, data=None): self._config = config_mod.config(data) self._readfiles = [] # list of read (path, fp, sections, remap) self._sections = {} if isinstance(data, self.__class__): # keep log self._readfiles.extend(data._readfiles) self._sections.update(data._sections) elif data: # record as changes self._logupdates(data) def copy(self): return self.__class__(self) def __contains__(self, section): return section in self._config def __getitem__(self, section): try: return self._sections[section] except KeyError: if self._config[section]: self._sections[section] = _wsortdict(self._config[section]) return self._sections[section] else: return {} def __iter__(self): return iter(self._config) def update(self, src): self._config.update(src) self._logupdates(src) def _logupdates(self, src): for s in src: self[s]._logupdate(src[s]) def set(self, section, item, value, source=''): self._setconfig(section, item, value, source) self[section]._logset(item, value) def _setconfig(self, section, item, value, source): if item not in self._config[section]: # need to handle 'source' self._config.set(section, item, value, source) else: self[section][item] = value def remove(self, section, item): del self[section][item] self[section]._logdel(item) def read(self, path, fp=None, sections=None, remap=None): self._config.read(path, fp, sections, remap) self._readfiles.append((path, fp, sections, remap)) def write(self, dest): ini = self._readini() self._replaylogs(ini) dest.write(str(ini)) def _readini(self): """Create iniparse object by reading every file""" if len(self._readfiles) > 1: raise NotImplementedError( "wconfig does not support read() more than once") def newini(fp=None): try: # TODO: optionxformvalue isn't used by INIConfig ? return INIConfig(fp=fp, optionxformvalue=None) except ConfigParser.ParsingError, err: raise error.ParseError(err.message.splitlines()[0], '%s:%d' % (err.filename, err.lineno)) if not self._readfiles: return newini() path, fp, sections, remap = self._readfiles[0] if sections: raise NotImplementedError("wconfig does not support 'sections'") if remap: raise NotImplementedError("wconfig does not support 'remap'") if fp: fp.seek(0) return newini(fp) else: fp = util.posixfile(path, 'rb') try: return newini(fp) finally: fp.close()
def _readStatus(self, ctx, ctx2, wfile, status, changeselect, force): def getstatus(repo, n1, n2, wfile): m = match.exact(repo.root, repo.getcwd(), [wfile]) modified, added, removed = repo.status(n1, n2, match=m)[:3] if wfile in modified: return 'M' if wfile in added: return 'A' if wfile in removed: return 'R' if wfile in ctx: return 'C' return None isbfile = False repo = ctx._repo maxdiff = repo.maxdiff self.flabel = u'<b>%s</b>' % self.filePath() if ctx2: # If a revision to compare to was provided, we must put it in # the context of the subrepo as well if ctx2._repo.root != ctx._repo.root: wsub2, wfileinsub2, sctx2 = \ hglib.getDeepestSubrepoContainingFile(wfile, ctx2) if wsub2: ctx2 = sctx2 absfile = repo.wjoin(wfile) if (wfile in ctx and 'l' in ctx.flags(wfile)) or \ os.path.islink(absfile): if wfile in ctx: data = ctx[wfile].data() else: data = os.readlink(absfile) self.contents = data self.flabel += _(' <i>(is a symlink)</i>') return if ctx2 is None: ctx2 = ctx.p1() if status is None: status = getstatus(repo, ctx2.node(), ctx.node(), wfile) mde = _('File or diffs not displayed: ' 'File is larger than the specified max size.\n' 'maxdiff = %s KB') % (maxdiff // 1024) if status in ('R', '!'): if wfile in ctx.p1(): fctx = ctx.p1()[wfile] if fctx._filelog.rawsize(fctx.filerev()) > maxdiff: self.error = mde else: olddata = fctx.data() if '\0' in olddata: self.error = 'binary file' else: self.contents = olddata self.flabel += _(' <i>(was deleted)</i>') elif hasattr(ctx.p1(), 'hasStandin') and ctx.p1().hasStandin(wfile): self.error = 'binary file' self.flabel += _(' <i>(was deleted)</i>') else: self.flabel += _(' <i>(was added, now missing)</i>') return if status in ('I', '?'): assert ctx.rev() is None self.flabel += _(' <i>(is unversioned)</i>') if os.path.getsize(absfile) > maxdiff: self.error = mde return data = util.posixfile(absfile, 'r').read() if not force and '\0' in data: self.error = 'binary file' else: self.contents = data return if status in ('M', 'A', 'C'): if ctx.hasStandin(wfile): wfile = ctx.findStandin(wfile) isbfile = True try: fctx, newdata = self._checkMaxDiff(ctx, wfile, maxdiff, force) except _BadContent: if status == 'A': self._checkRenamed(repo, ctx, ctx2, wfile) raise self.contents = newdata if status == 'C': # no further comparison is necessary return for pctx in ctx.parents(): if 'x' in fctx.flags() and 'x' not in pctx.flags(wfile): self.elabel = _("exec mode has been " "<font color='red'>set</font>") elif 'x' not in fctx.flags() and 'x' in pctx.flags(wfile): self.elabel = _("exec mode has been " "<font color='red'>unset</font>") if status == 'A': oldname = self._checkRenamed(repo, ctx, ctx2, wfile) if not oldname: return olddata = ctx2[oldname].data() elif status == 'M': if wfile not in ctx2: # merge situation where file was added in other branch self.flabel += _(' <i>(was added)</i>') return oldname = wfile olddata = ctx2[wfile].data() else: return self.olddata = olddata if changeselect: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = True m = match.exact(repo.root, repo.root, [wfile]) fp = cStringIO.StringIO() for c in patch.diff(repo, ctx.node(), None, match=m, opts=diffopts): fp.write(c) fp.seek(0) # feed diffs through parsepatch() for more fine grained # chunk selection filediffs = patch.parsepatch(fp) if filediffs and filediffs[0].hunks: self.changes = filediffs[0] else: self.diff = '' return self.changes.excludecount = 0 values = [] lines = 0 for chunk in self.changes.hunks: buf = cStringIO.StringIO() chunk.write(buf) chunk.excluded = False val = buf.getvalue() values.append(val) chunk.lineno = lines chunk.linecount = len(val.splitlines()) lines += chunk.linecount self.diff = ''.join(values) else: diffopts = patch.diffopts(repo.ui, {}) diffopts.git = False newdate = util.datestr(ctx.date()) olddate = util.datestr(ctx2.date()) if isbfile: olddata += '\0' newdata += '\0' difftext = mdiff.unidiff(olddata, olddate, newdata, newdate, oldname, wfile, opts=diffopts) if difftext: self.diff = ('diff -r %s -r %s %s\n' % (ctx, ctx2, oldname) + difftext) else: self.diff = ''