Previously convert would throw an exception if it encountered a git commit with
a .gitmodules file that was malformed (i.e. was missing, but had submodule
files, or was malformed).
Instead of breaking the convert entirely, let's print error messages and move
on.
Convert had a bug where it relied on repo.tip() to be the newly committed
commit. This was not the case if the commit already existed in the repository
(since repo.commitctx() did nothing, the tip() referenced some random other
commit and the revmap got corrupted).
This fixes it by using the node returned by repo.commitctx().
Python 2.6 introduced the "except type as instance" syntax, replacing
the "except type, instance" syntax that came before. Python 3 dropped
support for the latter syntax. Since we no longer support Python 2.4 or
2.5, we have no need to continue supporting the "except type, instance".
This patch mass rewrites the exception syntax to be Python 2.6+ and
Python 3 compatible.
This patch was produced by running `2to3 -f except -w -n .`.
Python 2.6 introduced a new octal syntax: "0oXXX", replacing "0XXX". The
old syntax is not recognized in Python 3 and will result in a parse
error.
Mass rewrite all instances of the old octal syntax to the new syntax.
This patch was generated by `2to3 -f numliterals -w -n .` and the diff
was selectively recorded to exclude changes to "<N>l" syntax conversion,
which will be handled separately.
One of the features of hgweb is that current position in repo history is
remembered between separate requests. That is, links from /rev/<node_hash> lead
to /file/<node_hash> or /log/<node_hash>, so it's easy to dig deep into the
history. However, such links could only use node hashes and local revision
numbers, so while staying at one exact revision is easy, staying on top of the
changes is not, because hashes presumably can't change (local revision numbers
can, but probably not in a way you'd find useful for navigating).
So while you could use 'tip' or 'default' in a url, links on that page would be
permanent. This is not always desired (think /rev/tip or /graph/stable or
/log/@) and is sometimes just confusing (i.e. /log/<not the tip hash>, when
recent history is not displayed). And if user changed url deliberately to say
default instead of <some node hash>, the page ignores that fact and uses node
hash in its links, which means that navigation is, in a way, broken.
This new property, symrev, is used for storing current revision the way it was
specified, so then templates can use it in links and thus "not dereference" the
symbolic revision. It is an additional way to produce links, so not every link
needs to drop {node|short} in favor of {symrev}, many will still use node hash
(log and filelog entries, annotate lines, etc).
Some pages (e.g. summary, tags) always use the tip changeset for their context,
in such cases symrev is set to 'tip'. This is needed in case the pages want to
provide archive links.
highlight extension needs to be updated, since _filerevision now takes an
additional positional argument (signature "web, req, tmpl" is used by most of
webcommands.py functions).
More references to symbolic revisions and related gripes: issue2296, issue2826,
issue3594, issue3634.
This is a step toward replacing the extdiff internals with archive, in order to
support 'extdiff -S'. Only Mercurial subrepos are supported for now.
If a file is missing from the filesystem, it is silently skipped. Perhaps it
should warn, but it cannot abort when working with extdiff because deleting a
file is a legitimate diff.
The previous patch made 'string' is always interpreted as a template. So
this patch removes the special handling of r'rawstring' instead. Now r''
disables template processing at all.
If the conversion doesn't change the hash, and the cset is public in the source,
it should be public in the destination. (This can happen if file remapping is
done that doesn't affect the initial commits.) This also propagates the secret
phase from the source, regardless of the hash, because presumably the content is
what is secret. Otherwise, the destination commit stays in the draft phase.
Maybe any draft cset with an unchanged hash should be changed to public, because
it has effectively been shared, but convert pretty strongly implies throwing
away (or at least readonly archiving) the source repo.
The change in the rollback output is because the name of the outer transaction
is now 'convert', which seems more accurate. Unfortunately, the memctx won't
indicate the hash prior to committing, so the proper phase can't be applied with
the commit.
The repo is already write locked in mercurial_sink.before().
This will be needed in the next patch to determine if phases need to be
adjusted. The insertion of the source revision in 'extras{}' is still
controlled by the config property.
Conversion of a merge starts with p1 and re-adds the files that were changed in
the merge or came unmodified from p2. Files that are unmodified from p1 will
thus not be touched and take no time. Files that are unmodified from p2 would be
retrieved and rehashed. They would end up getting the same hash as in p2 and end
up reusing the filelog entry and look like the p1 case ... but it was slow.
Instead, make getchanges also return 'files that are unmodified from p2' so the
sink can reuse the existing p2 entry instead of calling getfile.
Reuse of filelog entries can make a big difference when files are big and with
long revlong chains so they take time to retrieve and hash, or when using an
expensive custom getfile function (think
http://mercurial.selenic.com/wiki/ConvertExtension#Customization with a code
reformatter).
This in combination with changes to reuse filectx entries in
localrepo._filecommit make 'unchanged from p2' almost as fast as 'unchanged
from p1'.
This is so far only implemented for the combination of hg source and hg sink.
This is a refactoring/optimization. It is covered by existing tests and show no
changes - which is a good thing.
This function doesn't need access to any of the args or kwargs, so make the
monkeypatching more robust. (In upcoming patches we'll introduce another
argument to patch.diff, and this function would break if it weren't for this
patch.)
"working directory" is the standard term, we should use it consistently.
But I didn't touch the hint, "run 'hg update' to get a working copy", because
"get a working directory" sounds a bit odd.
The censor command is a core extension which can replace the contents of a
historical file revision with a censor "tombstone" which can be exchanged
with older clients in place of the real revision data. The command rewrites
the filelog by copying revision-by-revision.
Care must be taken to expand the fulltext of the children of the censored
revision before copying them to the new filelog; they might be stored as
deltas against the uncensored revision, and those deltas will be invalidated.
For more background on the censorship feature design, see:
http://mercurial.selenic.com/wiki/CensorPlan
For merges, we walk the files N-1 times, where N is the number of
parents. This means that for an octopus merge with 3 parents and 2
changed files, we actually fetch 6 files. This corrects the progress
output of the convert command when such commits are encountered.
Although Python supports `X = Y if COND else Z`, this was only
introduced in Python 2.5. Since we have to support Python 2.4, it was
a very common thing to write instead `X = COND and Y or Z`, which is a
bit obscure at a glance. It requires some intricate knowledge of
Python to understand how to parse these one-liners.
We change instead all of these one-liners to 4-liners. This was
executed with the following perlism:
find -name "*.py" -exec perl -pi -e 's,(\s*)([\.\w]+) = \(?(\S+)\s+and\s+(\S*)\)?\s+or\s+(\S*)$,$1if $3:\n$1 $2 = $4\n$1else:\n$1 $2 = $5,' {} \;
I tweaked the following cases from the automatic Perl output:
prev = (parents and parents[0]) or nullid
port = (use_ssl and 443 or 80)
cwd = (pats and repo.getcwd()) or ''
rename = fctx and webutil.renamelink(fctx) or []
ctx = fctx and fctx or ctx
self.base = (mapfile and os.path.dirname(mapfile)) or ''
I also added some newlines wherever they seemd appropriate for readability
There are probably a few ersatz ternary operators still in the code
somewhere, lurking away from the power of a simple regex.
After adding some sneaky debug printing[0], I determined that this
test flaked when a CVS commit containing two files starts too close to
the end of a second, thus putting file "a" in one second and "b/c" in
the following second. The secondary sort key meant that these changes
sorted in a different order when the timestamps were different than
they did when they matched. As far as I can tell, CVS walks through
the files in a stable order, so by sorting on the filenames in cvsps
we'll get stable output. It's fine for us to switch from sorting on
the branchpoint as a secondary key because this was already the point
when we didn't care, and we're just trying to break ties in a stable
way. It's unclear to be if having the branchpoint present matters
anymore, but it doesn't really hurt to leave it.
With this change in place, I was able to run test-convert-cvs over 650
times in a row without a failure. test-convert-cvcs-synthetic.t
appears to still be flaky, but I don't think it's *worse* than it was
before - just not better (I observed one flaky failure in 200 runs on
that test).
0: The helpful debug hack ended up being this, in case it's useful to
future flaky test assassins:
--- a/hgext/convert/cvsps.py
+++ b/hgext/convert/cvsps.py
@@ -854,6 +854,8 @@ def debugcvsps(ui, *args, **opts):
ui.write(('Branch: %s\n' % (cs.branch or 'HEAD')))
ui.write(('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1],
','.join(cs.tags) or '(none)')))
+ if cs.comment == 'ci1' and (cs.id == 6) == bool(cs.branchpoints):
+ ui.write('raw timestamp %r\n' % (cs.date,))
if cs.branchpoints:
ui.write(('Branchpoints: %s \n') %
', '.join(sorted(cs.branchpoints)))
Matt Harbison pointed out that my recent cdf4a99e1657 might cause
__contains__ to continously get replaced by another version that calls
itself, since the manifest instance returned by the super method is
always the same instance due to @propertycache. He also suggested
replacing the class instead, as is done with the context class in the
surrounding code. Do so.
We're soon going to add an alternative manifest class
(treemanifest). Rather than extending both those classes by
largesfiles versions, let's replace the method on the manifest
instances.
Rev cb4d72125aae adding a parameter here. This breaks third-party extensions
like crecord and also makes the issue fairly hard to fix on the extension's
side if it wants to retain compatibility across Mercurial versions -- in old
versions, the positional argument will be passed into the next unknown
argument, which is 'files'.
The patch also undoes a change to the record extension that is no longer
necessary.
In a previous commit we removed the extra histedit object instance being
constructed in --continue and --abort. The new --edit-todo missed this fix
though (which means the state object it produces doesn't have the locks on it).
It's not breaking anything now, but let's go ahead and clean that up before we
forget.
This fixes a mild case of cut-and-paste code regarding failing to set
terminal modes. This is evident in the win32 comment that is misplaced
for the terminfo mode since cset 1456f081d00e.
Instead, we refactor this C&P into a small local function.
It's pretty annoying to be getting this warning when already the
colour extension has no hope of working. If there isn't a human on the
other end to to see the colours, there probably isn't a human either
who cares about this warning. More likely, some script somewhere is
gonna get confused with the warning output.
Of course, if we still want to see the warning for some reason, we can
always set --config ui.interactive=True.
While using the record extension to select changes, the user couldn't see the
content of newly added files and had to select/reject them based on filename.
The test is changed accordingly in two places.
Before this change hg help histedit would use the default variable label:
--commands VALUE
...
-r --rev VALUE [+]
With this change the text will be in the usual help text style and a bit more
explanatory:
--commands FILE
...
-r --rev REV [+]
The rest of help messages for command arguments are simple phrases without any
ending punctuation, so having this text be a complete sentence didn't really
fit.
Previously, the source was silently skipped because the largefile was in the
list of changed files, but the standin was in the copies dictionary. The source
is only displayed if the changed file is a key in the copies dictionary.
It's probably possible to refactor so that the 'if m._cwd' check isn't
necessary, but the False case is the typical case (i.e. run from the root of the
repo), and simpler to read.
An exact path to a largefile from outside the repo was previously ignored.
match.rel('.hglf') will handle figuring out both the correct '../' length to the
standin directory if inside the repo, or path/to/repo from outside, at the cost
of a pconvert() to keep the patterns using '/' on Windows.
When logging '.hglf/foo', the pattern list was being transformed from
['.hglf/foo'] into ['.hglf/foo', '.hglf/.hglf/foo']. Aside from the
pathological case of somebody getting a directory named '.hglf' created inside
the standing directory, the old code shouldn't have had any bad effects.
(amended by mpm to sort patterns for test stability and not upset check-code)
Adding the standin to the patterns list was (possibly) harmless before, but was
wrong, because the pattern list was already updated above that code. Now that
patterns are handled, it was actually harmful. For example, in this test:
$ hg log -G glob:**another*
the adjusted pattern list would have been:
['glob:**another*', '.hglf/.', 'glob:.hglf/**another*']
which causes every largefile in the root to be matched.
I'm not sure why 'glob:a*' picks up the rename of a -> b commit in test-log.t,
but a simple 'a' doesn't. But it doesn't appear to be caused by the largefiles
extension.
Since many users are using terminals wider than 80 chars there should be an
option to have longer lines in histedit editor.
Even if the summary line is shorter than 80 chars after adding action line
prefixes (like "pick 7c2fd3b9020c") it doesn't fit there anymore. Setting
it to for example 110 would be a nice option to have.
Monotone used '1' for close while core Mercurial use 1. Now, for consistency,
use the same value everywhere. It will be stored as a string anyway and the
change will not make any real difference.
(The actual value of 'close' doesn't matter as long as extras has such a key.)
All current callers supply some sort of prefix, so the issue was hidden. But if
no parameter was specified, a crash occurred in the write() closure when
concatenating 'prefix' and 'name'.
When there isn't lfdirstate file in cases below, "openlfdirstate()"
call "scmutil.match()" indirectly to build lfdirstate up.
- subrepos disabling largefiles locally
- lfdirstate file is missed accidentally
This causes infinite recursive call of "openlfdirstate()" in
"overriderevert()" (introduced by 25febe9568dd), because
"openlfdirstate()" is invoked from the function overriding
"scmutil.match()" itself.
To avoid infinite recursive call of "openlfdirstate()" in
"overriderevert()" in such cases, this patch passes "create=False"
argument to "openlfdirstate()".
"create=False" forcibly makes "openlfdirstate()" avoid code path to
build lfdirstate up.
Even if largefiles extension is enabled in a repository, "repo"
object, which isn't "largefiles.reposetup()"-ed, is passed to
overridden functions in the cases below unexpectedly, because
extensions are enabled for each repositories strictly.
(1) clone without -U:
(2) pull with -U:
(3) pull with --rebase:
combination of "enabled@src", "disabled@dst" and
"not-required@src" cause this situation.
largefiles requirement
@src @dst @src result
-------- -------- --------------- --------------------
enabled disabled not-required aborted unexpectedly
required requirement error (intentional)
-------- -------- --------------- --------------------
enabled enabled * success
-------- -------- --------------- --------------------
disabled enabled * success (only for "pull")
-------- -------- --------------- --------------------
disabled disabled not-required success
required requirement error (intentional)
-------- -------- --------------- --------------------
(4) update/revert with a subrepo disabling largefiles
In these cases, overridden functions cause accessing to largefiles
specific fields of not "largefiles.reposetup()"-ed "repo" object, and
execution is aborted.
- (1), (2), (4) cause accessing to "_lfstatuswriters" in
"getstatuswriter()" invoked via "updatelfiles()"
- (3) causes accessing to "_lfcommithooks" in "overriderebase()"
For safe accessing to these fields, this patch examines whether passed
"repo" object is "largefiles.reposetup()"-ed or not before accessing
to them.
This patch chooses examining existence of newly introduced
"_largefilesenabled" instead of "_lfcommithooks" and
"_lfstatuswriters" directly, because the former is better name for the
generic "largefiles is enabled in this repo" mark than the latter.
In the future, all other overridden functions should avoid largefiles
specific processing for efficiency, and "_largefilesenabled" is better
also for such purpose.
BTW, "lfstatus" can't be used for such purpose, because some code
paths set it forcibly regardless of existence of it in specified
"repo" object.
The previous code was adding standin files to the matcher's file list when
neither the standin file nor the original existed in the context. Somehow, this
was confusing the logging code into behaving differently from when the extension
wasn't loaded.
It seems that this was an attempt to support naming a directory that only
contains largefiles, as a test fails if the else clause is dropped entirely.
Therefore, only append the "standin" if it is a directory. This was found by
running the test suite with --config extensions.largefiles=.
The first added test used to log an additional cset that wasn't logged normally.
The only relation it had to file 'a' is that 'a' was the source of a move, but
it isn't clear why having '.hglf/a' in the list causes this change:
@@ -47,6 +47,11 @@
Make sure largefiles doesn't interfere with logging a regular file
$ hg log a --config extensions.largefiles=
+ changeset: 3:2ca5ba701980
+ user: test
+ date: Thu Jan 01 00:00:04 1970 +0000
+ summary: d
+
changeset: 0:9161b9aeaf16
user: test
date: Thu Jan 01 00:00:01 1970 +0000
The second added test used to complain about a file not being in the parent
revision:
@@ -1638,10 +1643,8 @@
Ensure that largefiles doesn't intefere with following a normal file
$ hg --config extensions.largefiles= log -f d -T '{desc}' -G
- @ c
- |
- o a
-
+ abort: cannot follow file not in parent revision: ".hglf/d"
+ [255]
$ hg log -f d/a -T '{desc}' -G
@ c
|
Note that there is still something fishy with the largefiles code, because when
using a glob pattern like this:
$ hg log 'glob:sub/*'
the pattern list would contain '.hglf/glob:sub/*'. None of the tests show this
(this test lives in test-largefiles.t at 1349), it was just something that I
noticed when the code was loaded up with print statements.
Convert will try to find references to revisions in commit messages and replace
them with references to the converted revision. It will take any string that
looks like a hash (and thus also decimal numbers) and look it up in the source
repo. If it finds anything, it will use that in the commit message instead.
It would do that for all hex digit sequences of 6 to 40 characters. That was
usually no problem for small repos where it was unlikely that there would be a
matching 6 'digit' hash prefix. It was also no problem on repos with less than
100000 changesets where numbers with 6 or more digits not would match any
revision number. With more than 100000 revisions random numbers in commit
messages would be replaced with a "random" hash. For example, 'handle 100000
requests' would be changed to to 'handle 9117c6 requests'. Convert could thus
not really be used on real repositories with more than 100000 changesets.
The default hash length shown by Mercurial is 12 'digits'. It is unexpected and
unwanted that convert by default tries to replace revision references that use
less than that amount of 'digits'.
To fix this, don't match strings that are less than the default hash size of 12
characters.
Before this changeset rebase was getting very confused if any revision in the
rebase set became hidden. This was fairly easy to achieve if a rebased revision
was made visible by the working copy location. The rebase process would update
somewhere else and the revision would become hidden.
To work around this issue, we ensure rebased revisions remain visible for the
whole process.
This is a simple change suitable for stable. More subtle usage of unfiltered
repository in rebase may solve this issue more cleanly.
b8552020f458 broke things ... and the following cleanups didn't fix all issues.
It didn't work with the diffargs shipped in mergetools.rc with explicit
quoting. Parameters would end up with being quoted twice - especially if they
really needed quoting.
To work around that, look for explicit quotes around the variables that will be
substituted with proper quoting. Also accept an additional prefix so we can
handle both
--foo='$parent'
and
'--foo=$parent'
It will however still fail if the user intentionally place the variable inside
a quoted string, as in
'parent $parent is on the left'
There is currently no good way to handle that, short of knowing exactly which
quoting mechanism will be used.
This effectively reverts 9fc565fa1621, which caused some normal file copies to
not be displayed as copies. Other normal file copies could be displayed- the
exact reason isn't clear. This also adds two tests that were failing prior to
this backout, so that this can be sorted out next cycle.
The difference between copy cases that worked and those that didn't seemed to be
in copies.pathcopies(). When largefiles isn't enabled for the changed test, or
lfstatus is not set in the commands.status() override, 'y.ancestor(x) == x'.
That wasn't true otherwise, which fell through to the _chain() method. In this
case, the copy is removed in the criss cross loop.
'y.ancestor(x)' returns a context.changectx type, while 'x' is a lfilesctx type
in the failing case. I tried adding the ancestor method to the lfilesctx class
to change the type of the ancestor context, however the context when printed as
a string then gains a '+'. This points to it being a context.committablectx,
which clearly isn't correct for an ancestor. Possibly the problem is the
lfilesctx needs to subclass context.committablectx in some cases, but
context.changectx in others, within the same invocation? I'm not sure how to
pull that off, and backing out this change is safer during the freeze.
As to the status changing when a path is specified, I haven't looked into it
yet.
We use -T consistently elsewhere to refer to the --template option.
The old -t option is now renamed to --oldtemplate so that -t still
works. This has the benign side effect of introducing and immediately
deprecating a new long option.
We also test with both -t and -T options.
Previously, when a largefile is forgotten and then reverted, a warning was
issued:
$ hg revert -R subrepo subrepo/large.txt
file not managed: subrepo/large.txt (glob)
This was purely cosmetic as the file itself actually was reverted.
The problem was even with all of the matcher patching, the largefile pattern
given on the command line wasn't converted to a standin because the standin was
neither in ctx nor wctx. This causes the named largefile to be added to the
'names' dict in cmdutil.revert() in the repo walk at line 2550. The warning was
printed out when the 'names' dict is iterated, because the file was specified
exactly.
Since core revert recurses into subrepos and largefiles only overrides the
revert method in commands.py, it doesn't work properly when reverting a subrepo.
However, it still will recurse into the subrepo and call the installed matcher
method, so lfdirstate is reopened for the current repo level to prevent any new
problems.
Previously, the histedit state object was being recreated during continue/abort.
This meant that the locks that were held on the original state object were not
available to actions, which meant actions could not release the lock on the
repository (like an 'exec' action would need to do).
This affected our internal extension that added the 'exec' action.
This is in line with the documentation on the base class method, and is related
to issue4496 (but doesn't fix the reporter's problem of not mangling other data
that matches a revision pattern). Now instead of aborting when there is an
ambiguous source rev, it simply won't update the commit comment. A warning
message might be nice, but a None return masks whether the problem was no
matching revision, or more than one.
The only other caller of this is the logic that converts tags, but those are
never ambiguous since they are always 40 characters.
A test isn't feasible because there simply aren't enough commits in the test
suite repos to have an ambiguous identifier that is at least 6 characters long,
and it would be too easy for the ambiguity to disappear when unrelated changes
are made. Instead, I simply ran 'hg --traceback log -r c' on the hg repo, and
handled the error it threw.
When a directory is named in the commit file list, the previous behavior was to
walk the list, and if no normal files in the directory were also named, add the
corresponding standin for each largefile in that directory. The directory is
then dropped from the list, so that committing a directory with no normal file
changes works. It then added the corresponding standin directory for the first
largefile seen, by prefixing it with '.hglf/'.
The latter is unnecessary since each affected largefile is explicitly referenced
by its standin in the list. It also caused an abort if there were no changed
largefiles in the directory, because none of its standins changed:
abort: .hglf/foo/bar: no match under directory!
This list of files is used to tweak a matcher in lfutil.updatestandinsbymatch(),
which is what is passed to commit().
The status() call that is ultimately done in the commit code with this matcher
seems to have some OS specific differences. It is not necessary to append '.'
for Windows to run the largefiles tests cleanly. But if '.' is not added to the
list, the match function isn't called on Linux, so status() would miss any
normal files that were also in a named directory. The commit then proceeds
without those normal files, or says "nothing changed" if there were no changed
largefiles in the directory. This is not filesystem specific, as VFAT on Linux
had the same behavior as when run on ext4. It is also not an issue with
lfilesrepo.status(), since that only calls the overridden implementation when
paths are passed to commit. I dont have access to an OS X machine ATM to test
there.
Maybe there's a better way to do this. But since the standin directory for the
first largefile was previously being added, and that caused the same walk in
status(), there's no preformance change to this. There is no danger of
erroneously committing files in '.', because the original match function is
called, and if it fails, the lfutil.updatestandinsbymatch() tweaked matcher only
indicates a match if the file is in the list of standins- and '.' never is. The
added tests confirm this.
The next diff will add support for writing bundle2 files to writebundle, but
the bundle2 generator wants access to a ui object. This changes the signature
and callsites to pass one in.
Standins are read before and after an update/merge, and all the standins that
changes are handed to updatelfiles for getting their corresponding largefiles
updated. updatelfiles would then hash the largefile and see if it already
matched the new expected hash. If so, it would skip the update. If different,
the largefile would be updated.
It would happen very rarely that the largefile happened to match the new hash
(and thus not the old one) and the hashing would thus be pointless ... and
hashing is not cheap.
Instead, when it is known that the standin hash changed (from an update), just
update the standin unconditionally. If the largefile was "unsure" before the
update, it was hashed at that point, so we know there is nothing to preserve.
(Also, the hashing in updatelfiles was not used to preserve changes, but only
to be lazy about updating the largefile, so nothing is lost by not doing this
extra hashing.)
There might be rare situations where we now will update largefiles that didn't
have to be updated, but in all relevant cases (?) this will improve
performance.
Updates on a repo with some big largefiles has been seen to go from 9.19 s to
6.8 s - that is 26% less painful.
The --large, --normal and --lfsize args couldn't be passed to a subrepo before,
and files in the subrepos would be added silently (if -v wasn't specified) as
normal files. As an added bonus, 'hg add --dry-run' no longer prints that
largefiles would also be added as normal files as well.
0e5f75a52c9d introduced a way to share bookmarks. When a repository share that
shares bookmarks was created, a .hg/bookmarks.shared file was created to mark
the repository share as one that shares its bookmarks.
We have plans to introduce other levels of sharing, including a "full share"
mode. Rather than creating a new ".shared" file for each new thing that we may
want to share It seems better to create a single "shared" file that will list
what is shared for a given shared repository. This should make it much easier
to get a list of everything that is shared by a given shared repository.
The shared file contains a list of shared "items" (such as bookmarks). Each
shared "item" is added as a new line in the file. For now the only possible
entry in the file is "bookmarks".
This change touches every module in which repository.wopener was being used, and
changes it for the equivalent repository.wvfs.
It should now be possible to remove localrepo.wopener.
This change touches every module in which repository.sopener was being used, and
changes it for the equivalent repository.svfs.
It should now be possible to remove localrepo.sopener.
This change touches every module in which repository.opener was being used, and
changes it for the equivalent repository.vfs. This is meant to make it easier
to split the repository.vfs into several separate vfs.
It should now be possible to remove localrepo.opener.
'hg update' would hash all 'unsure' largefiles before performing the merge. It
would update the standins but not detect the very common case where the
largefile never had been changed by the user but just had been marked with an
invalid dirstate mtime to make sure any changes done by the user in the same
second would be detected. The largefile would remain in that state and would
have to be hashed again next time even though it still not had been changed.
Sad trombone.
Instead, for largefiles listed as 'unsure' or 'modified', after updating the
standin with the actual hash, mark the largefile as normal if it turns out to
not be modified relative to the revision in the parent revision. That will
prevent it from being hashed again next time.
If resolving a merge conflict result in an empty changesets, we now properly
skip the changeset instead of crashing.
Original patch from Robert Collins <robertc@robertcollins.net>.
This will be used to exclude largefile candidates from the normal file matcher,
which will allow add and addremove dryruns to not print a file as both a normal
and a large file.
Core addremove prints the file relative to cwd only if patterns are provided to
the command. Core add always prints relative to cwd. Also, both methods print
the subrepo prefix when needed. The 'already a largefile' doesn't have an
analog in core, but follows the same rules for consistency.
Both cmdutil.remove() and scmutil.addremove() require verbose mode or an inexact
match to print the filename. Core addremove also prints the file relative to
cwd only if patterns are provided to the command. And finally, both methods
print the subrepo prefix when needed.
Currently, if the node no longer exists, the state object fails to load
and pukes with an exception. Changing the state object to only store the
node allows callers to handle these cases. For instance, in
bootstrapcontinue we can now detect that the node doesn't exist and exit
gracefully.
The alternative is to have the state object store something like None
when the node doesn't exist, but then outside callers won't be able to
access the old node for recovery (unless we store both the node and the
ctx, but why bother).
More importantly it allows us to detect this case when doing hg histedit
--abort. Currently this situation results in both --continue and
--abort being broken and the user has to rm .hg/histedit-state to unwedge
their repo.
(description by Durham Goode)
During histedit we don't want user to do any operation resulting in
stripping nodes needed to continue history editing. This patch
wraps the strip function to detect such situations.
MSYS on Windows has a terminal that supports the "win32" color mode
(which "auto" properly detects for us). However, a popularily configured
pager in that environment (GNU less) only supports the "ansi" color
mode.
This patch teaches color about a new config option: pagermode. It
behaves like "mode" but is only consulted when the pager is active for
the current command. MSYS users can now set "pagermode = ansi" and get a
colorful experience that just works. Previously, MSYS users would have
to live without color when using GNU less as the pager, would have to
manually configure the pager to attend every command, or would have
gibberish if "ansi" was used without the pager.
An upcoming patch will teach color to potentially act differently if the
pager is active. Since both extensions wrap the same function
(dispatch._runcommand) to change behavior, we must guarantee that
pager's wrapped function runs before color's so color may read the
breadcrumb left by pager.
A subsequent patch will teach the color extension to do different things
depending on whether a pager is active. This patch leaves a breadcrumb
on the ui instance to allow it do that that.
When cloning a repo that requires largefiles, the user had to either enable the
extension on the command line and then manually edit the local hgrc file after
the clone, or just enable it globally for the user. Since it is a feature of
last resort, and materially affects even repos without any largefiles when it is
enabled, we should make it easier to not have it enabled globally.
This simply adds the enabling statement to the local hgrc if the requires file
mandates its use (which only happens after the first largefile is committed).
That means that a user who works with a mix of largefile and normal repos can
always clone with '--config extensions.largefiles=', and the extension is
permanently enabled or not as appropriate.
The change in test-largefiles.t is simply because the order of loading rebase
and largefiles changed. The same change occurs if the order is flipped in the
hgrc file at the top of the test.
The current color mode detection on Windows assumes the presence of the
TERM environment variable assumes ANSI is supported. However, this isn't
always true. In MSYS (commonly found as part of MinGW), TERM is set to
"cygwin" and the auto resolved color mode of "ansi" results in escape
sequences getting printed literally to the terminal. The output is
very difficult to read and results in a bad user experience. A
workaround is to activate the pager and have it attend all commands (GNU
less in MSYS can render ANSI terminal sequences properly).
In Cygwin, TERM is set to "xterm." Furthermore, Cygwin supports
displaying these terminal sequences properly (unlike MSYS).
This patch changes the mode auto-detection logic on Windows to be more
conservative about selecting the "ansi" mode. We now only select the
"ansi" mode if TERM is set and it contains the string "xterm" or if
we were unable to talk to win32 APIs to determine the settings. There is
a chance this may take away "ansi" from a terminal that actually
supports it. The recourse for this would be to patch the detection to
act appropriately and to override color.mode until that patch has
landed. However, the author believes this regression is tolerable, since
it means MSYS users won't have gibberish printed by default.
Since MSYS's common pager (less) supports display of ANSI sequences,
there is room to patch the color extensions so it can select the ANSI
color mode if a pager is activated.
Mozilla (being an active user of MSYS) would really appreciate this
being part of the stable branch. However, since I believe it is BC, I
haven't explicitly requested application to stable since I figure that
request will be denied.
Adds a configuration setting for allowing users to specify the default behavior
of 'hg histedit' without arguments. This saves users from having to manually
figure out the bottom commit or a complicated revset. My current revset of
choice is "only(.) & draft() - ::merge()"
The commits that histedit can work with is usually quite limited, so if this
feature ends up working well, we may want to consider making "only(.) & draft()
- ::merge()" the default behavior for everyone.
The destination is validated by pathutil.canonpath() for illegal components, and
that it is in the repository. The logic for creating the standin directory tree
was calling this before cmdutil.copy(), but without the destination file name
component. The cmdutil.copy() logic also calls pathutil.canonpath(), but with
the file name component. By always calling the core logic first, the error
message is always consistent. Specifically, the old behavior for these tests
was to say '.hg' contains an illegal component, and '..' is not under root.
A user wasn't likely to notice the discrepancy, but this eliminates a needless
difference when running the test suite with --config extensions.largefiles=.
Previously histedit only stored the short version of the rule nodes in the
state. This meant that later we couldn't resolve a rule node to its full
form if the commit had been deleted from the repo.
Let's store the full form from the beginning.
This is consistent with addlargefiles(), and will make it easier to get the
paths that are printed correct when recursing into subrepos or invoking from
outside the repository. It also now restricts the path that the addremove is
performed on if a path is given, as is done with normal files.
The repo.status() call needs to exclude clean files when performing an
addremove, because the addremove override method calling this used to pass the
list of files to delete, which caused the matcher to only consider those files
in building the status list. Now the matcher is restricted only to the extent
that the caller requested- usually directories if at all. There's no reason for
addremove to care about clean files anyway- we don't want them deleted.
The code for picking a merge ancestor when rebasing merges had a long and
incorrect comment.
The comment would perhaps have been fine as commit message but does
not make the code more readable or maintainable and is a bad
substitute for correct and readable code.
The correct essense of the comment is quite trivial: a merge of an ancestor of
the rebase destination and an 'outside' revision can be rebased as if it was a
linear change, using 'destination ancestor parent' as base and pretty much
ignoring the 'outside' revision.
The code path where the comment is placed is however also used for other kinds
of merge rebases. The comment is thus not really correct and not helpful. I
think it would be better to drop the comment and rewrite the code.
The more aggressive synchronization of lfdirstate that was backed out in
4fe80f20ab06 masked the problem where lfdirstate would hold an 'R' for a
largefile that was added and then removed without a commit between. We could
just conditionally call lfdirstate.drop() or lfdirstate.remove() here, but this
also properly updates lfdirstate if the standin doesn't exist for the file
somehow (i.e. call drop instead of remove).
Without this change, the precommit status in the commit command immediately
after the test change lists the removed (and never committed) largefile as 'R'.
It can also lead to situations where the status command reports the same, long
after the commit [1].
[1] http://www.selenic.com/pipermail/mercurial-devel/2015-January/065153.html
d20af8be6a14 introduced a significant performance regression: All largefiles
were marked 'normallookup' by linear (or noop) updates and had to be rehashed
by the next command.
The previous change introduced a different solution to the problem d20af8be6a14
solved and we can thus back it out again.
This is an alternative solution to the problem addressed by d20af8be6a14. This
implementation has the advantage that it doesn't mark clean largefiles as
normallookup. We can thus avoid repeated rehashing of all largefiles when
d20af8be6a14 is backed out.
This implementation use the existing 'lfmr' actions that 4f7f7352d9d0
introduced for handling another part of the same cases.
If an uncommitted and deleted file was forgotten, a warning would be emitted,
even though the operation was successful. See the previous patch for
'remove -A' for the exact circumstances, and details about the cause.
The bug report doesn't mention largefiles, but the given recipe doesn't fail
unless the largefiles extension is loaded. The problem only affected normal
files, whether or not any largefiles are committed, and only files that have
not been committed yet. (Files with an 'a' state are dropped from dirstate,
not marked removed.) Further, if the named normal file never existed, the
warning would be printed out twice.
The problem is that the core implementation of remove() calls repo.status(),
which eventually triggers a dirstate.walk(). When the file isn't seen in the
filesystem during the walk, the exception handling finds the file in
dirstate, so it doesn't complain. However, the largefiles implementation
called status() again with all of the original files (including the normal
ones, just dropped). This time, the exception handler doesn't find the file
in dirstate and does complain. This simply excludes the normal files from
the second repo.status() call, which the largefiles extension has no interest
is processing anyway.
This is a copy/paste (with the necessary tweaks) of the composenormalfilematcher
method currently on default, which does the inverse- this trims the normal files
out of the matcher. It will be used in the next patch.
This is in the way of passing a matcher to removelargefiles(). This method is
called in exactly two places- first in overrides.addremove() (but only if the
pattern list passed to it is not empty), and second in the commands.remove()
override. But since the latter calls commands.remove() first, which also does
this check, it isn't needed here.
To reduce amount of changes for review-ability, previous patch uses
"args" as argument name of "dodiff()", even though "args" includes
also the name of command to be executed (or full-path of it).
This patch replaces "args" by more appropriate name "cmdline".
Before this patch, all command line arguments for external tools are
quoted by the combination of "shlex.split" and "util.shellquote". But
this causes some problems.
- some problematic commands can't work correctly with quoted arguments
For example, 'WinMerge /r ....' is OK, but 'WinMerge "/r" ....' is
NG. See also below for detail about this problem.
https://bitbucket.org/tortoisehg/thg/issue/3978/
- quoting itself may change semantics of arguments
For example, when the environment variable CONCAT="foo bar baz':
- mydiff $CONCAT => mydiff foo bar baz (taking 3 arguments)
- mydiff "$CONCAT" => mydiff "foo bar baz" (taking only 1 argument)
For another example, single quoting (= "util.shellquote") on POSIX
environment prevents shells from expanding environment variables,
tilde, and so on:
- mydiff "$HOME" => mydiff /home/foobar
- mydiff '$HOME' => mydiff $HOME
- "shlex.split" can't handle some special characters correctly
It just splits specified command line by whitespaces.
For example, "echo foo;echo bar" is split into ["echo",
"foo;echo", "bar"].
On the other hand, if quoting itself is omitted, users can't specify
options including space characters with "--option" at runtime.
The root cause of this issue is that "shlex.split + util.shellquote"
combination loses whether users really want to quote each command line
elements or not, even though these can be quoted arbitrarily in
configurations.
To resolve this problem, this patch does:
- prevent configurations from being processed by "shlex.split" and
"util.shellquote"
only (possibly) "findexe"-ed or "findexternaltool"-ed command path
is "util.shellquote", because it may contain whitespaces.
- quote options specified by "--option" via command line at runtime
This patch also makes "dodiff()" take only one "args" argument instead
of "diffcmd" and "diffopts. It also omits applying "util.shellquote"
on "args", because "args" should be already stringified in "extdiff()"
and "mydiff()".
The last hunk for "test-extdiff.t" replaces two whitespaces by single
whitespace, because change of "' '.join()" logic causes omitting
redundant whitespaces.
Up until now we compared the "path" and "sharedpath" repository properties to
check if a repository is shared. This was relying an implementation detail of
shared repositories. In order to make it possible to change the way shared
repositories are implemented, we encapsulate this check into its own localrepo
method, called shared.
This new method returns None if the repository is shared, and something else
(for now a string describing the short of share) otherwise.
The reason why I did not call this method "isshared" and made it return a
boolean is that I plan to introduce a new type of shared repository soon.
# NOTES:
This is the first patch in a series whose purpose is to add support for
creating "full repository shares", which are repositories that share everything
with the repository source except their current revision, branch and bookmark.
This series is RFC because I am not very sure of some of the solutions I took.
Comments are welcome!
The comment about status being buggy with a repo proxy seems to be that status
wasn't being redirected to testing the largefiles themselves- lfstatus was
always False, and so the original status method was being called instead of
doing the largefiles processing. This is because when the various largefile
command overrides call 'repo.lfstatus = True', __setattr__() in repoview is in
turn setting the value on the unfiltered repo, and the value in the filtered
repo remains False.
Explicitly looking at the attribute on the unfiltered repo keeps all views in
sync.
There is no --after for addremove, so the printing for addremove can be hoisted
out of the 'not after' check. The difference between the two remove messages
reflects the existing difference between core remove and core addremove styles
for printing the file.
There are still some pre-existing issues here. Core addremove only prints on
inexact matches or when verbose. But since the largefiles that are being
removed are passed to removelargefiles() as a pattern list, there is never an
inexact match, which would keep the largefiles from being printed at all unless
verbose is specified. Therefore, the output is a little more aggressive than
core. The addremove print style here is also inconsistent with core- it should
use matcher.uipath(f) instead of f. These can be fixed once a matcher is passed
in.
The function only adds the hash content of the file to the set to upload if the
file in the ctx is a standin. It is called by overrides.summaryremotehook(),
which is called in the summary method. The largefiles extension switches
'lfstatus' on in summary, so the standins shouldn't be visible when obtaining a
context there.
The reason this wasn't noticed before is that the 'lfstatus' attribute is only
being set on the unfiltered repo because of how repoview delegates attribute
assignment. Therefore any filtered view will return a context containing
standins, whether or not 'lfstatus' was set in the various overrides methods.
That will be fixed in the next patch. But without this change, the next patch
would have test failures for 'summary --large' stating there are no files to
upload.
When a directory was renamed and a new untracked file was added in the
new directory and the remote directory added a file by the same name
in the old directory, the local untracked file gets overwritten, as
demonstrated by the broken test case in test-rename-dir-merge.
Fix by checking for unknown files for 'dg' actions too. Since
_checkunknownfile() currently expects the same filename in both
contexts, we need to add a new parameter for the remote filename to
it.
This simplifies largefiles' overridecalculateupdates(), which no
longer has to do the conversion it started doing in 478d610ca1b0
(largefiles: rewrite merge code using dictionary with entry per file,
2014-12-09).
To keep this patch small, we'll leave the name 'actionbyfile' in
overrides.py. It will be renamed in the next patch.
The hack for method monkey patching on repoview has been ruled out as
fragile, so we are rolling it back. We'll expand the explanation in the next
changeset.
The stored path contains platform specific separators, so splitting on '/.hg'
returned the string unmodified on Windows. The source was then looked for in
$source/.hg/.hg, which obviously fails. This caused cascading errors in
test-share.t relating to the recent bookmark support.
Merged files are considered modified at commit time even if only 1 parent
differs. In this case we must use the change context of this parent for
expansion.
The issue went unnoticed for long because it is only apparent until the next
update to the merge revision - except in test-keyword where it was always
staring us in the face.
This patch adds the -B/--bookmarks option to the share command added by the
share extension. All it does for now is create a marker, 'bookmarks.shared',
that will be used by future code to implement the sharing functionality.
Unicode and Python's unicode.splitlines() treat several extra legacy
ASCII codepoints as linebreaks, even though the vast bulk of computing
and Python's own str.splitlines() do not. Rather than introduce line
numbering confusion, we filter them out when highlighting.
The state mapping also contains some magic negative values (detached
parent, ignored revision). Blindly reading the state thus lead to
unfortunate usage of the negative value as an update destination. We
now filter them out.
We do a minor alteration of the test to catch this.
Mq tried to insert headers in the right order. Sometimes it would stop
searching before checking all headers and it could thus duplicate a header
instead of replacing it.
Changeset 5b64e22ecd8e introduced the examination of exec bit of
largefiles in "hg status --rev REV" case, but it doesn't avoid it on
the platform being unaware of exec-bit (e.g. on NTFS of Windows).
Fix inconsistent handling of plain header separation in mq patcheader - and
contrary to 05acc6157816, do it in the direction of having an empty line
between header and description. Plain patches are like mails and should thus
have an empty line between headers and body in compliance with RFC 822 3.1.
The new rebase revset didn't check for the case when there are no common
ancestors. Now it does. The new behavior should be the same as the pre-3.2
behavior. Added a test.
We have our own fast-path logic to see if something passes a sniff
test for being a Subversion repository, but it's possible for a user
to svnsync a repo using svn 1.8 and then use svn 1.7 bindings (as in
the bug) to try and convert the repo. If we at least tell the user the
version of libsvn that we used, they might get enough of a hint to
check on their own for format incompatibilities between their
svn{admin,sync} and the libsvn used by hg.
The current state of subrepo methods is to pass a 'ui' object to some methods,
which has the effect of overriding the subrepo configuration since it is the
root repo's 'ui' that is passed along as deep as there are subrepos. Other
subrepo method are *not* passed the root 'ui', and instead delegate to their
repo object's 'ui'. Even in the former case where the root 'ui' is available,
some methods are inconsistent in their use of both the root 'ui' and the local
repo's 'ui'. (Consider hg._incoming() uses the root 'ui' for path expansion
and some status messages, but also calls bundlerepo.getremotechanges(), which
eventually calls discovery.findcommonincoming(), which calls
setdiscovery.findcommonheads(), which calls status() on the local repo 'ui'.)
This inconsistency with respect to the configured output level is probably
always hidden, because --verbose, --debug and --quiet, along with their 'ui.xxx'
equivalents in the global and user level hgrc files are propagated from the
parent repo to the subrepo via 'baseui'. The 'ui.xxx' settings in the parent
repo hgrc file are not propagated, but that seems like an unusual thing to set
on a per repo config file. Any 'ui.xxx' options changed by --config are also
not propagated, because they are set on repo.ui by dispatch.py, not repo.baseui.
The goal here is to cleanup the subrepo methods by dropping the 'ui' parameter,
which in turn prevents mixing subtly different 'ui' instances on a given subrepo
level. Some methods use more than just the output level settings in 'ui' (add
for example ends up calling scmutil.checkportabilityalert() with both the root
and local repo's 'ui' at different points). This series just goes for the low
hanging fruit and switches methods that only use the output level.
If we really care about not letting a subrepo config override the root repo's
output level, we can propagate the verbose, debug and quiet settings to the
subrepo in the same way 'ui.commitsubrepos' is in hgsubrepo.__init__.
Archive only uses the 'ui' object to call its progress() method, and gitsubrepo
calls status().
This does not cause any behavioral change unless a 'bookmarks.shared' marker
file exists. A future change will add UI to create this file when a repository
is shared.
By moving the cd/dc prompts out of calculateupdates(), we let
largefiles' overridecalculateupdates() so the unresolved values
(i.e. 'cd' or 'dc' rather than 'g', 'r', 'a' and missing). This allows
overridecalculateupdates() to ask the user whether to keep the normal
file or the largefile before the user gets the cd/dc prompt. Whichever
answer the user gives, we make overridecalculateupdates() replace 'cd'
or 'dc' action, saving the user one annoying (and less clear)
question.
The recursive addremove operation occurs completely before the first subrepo is
committed. Only hg subrepos support the addremove operation at the moment- svn
and git subrepos will warn and abort the commit.
Instead of iterating over 'g' action, first find the set of all files
that are largefiles in p1. Then iterate over these files. This
prepares for considering actions other than 'g'.
In overridecalculateupdates(), we currently only deal with conflicts
that result in a 'g' action for either the largefile or a standin. We
will soon want to deal cases with 'cd' and 'dc' actions here. It will
be easier to reason about such cases if we rewrite it using a dict
from filename to action.
A side-effect of this change is that the output can only have one
action per file (which should be a good change). Before this change,
when one of the tests in test-issue3084 received this input (the 'a'
in the input was a result of 'cd' conflict resolved in favor of the
modified file):
'g': [('.hglf/f', ('',), 'remote created')],
'a': [('f', None, 'prompt keep')],
and the user chose to keep the local largefile, it produced this
output:
'g': [('.hglf/f', ('',), 'remote created')],
'r': [('f', None, 'replaced by standin')],
'a': [('f', None, 'prompt keep')],
Although 'a' actions are processed after 'r' actions by
recordupdates(), it still worked because 'a' actions have no effect on
merges (only on updates). After this change, the output is:
'g': [('.hglf/f', ('',), 'remote created')],
'r': [('f', None, 'replaced by standin')],
Similarly, there are several tests in test-largefiles-update that get
inputs like:
'a': [('.hglf/large2', None, 'prompt keep')],
'g': [('large2', ('',), 'remote created')],
and when the user chooses to keep the local largefile, they produce
this output:
'a': [('.hglf/large2', None, 'prompt keep'),
('.hglf/large2', None, 'keep standin')],
'lfmr': [('large2', None, 'forget non-standin largefile')],
In this case, it was not a merge but an update, so the 'a' action does
have an effect. However, since dirstate.add() is idempotent, it still
has no obserable effect.
After this change, the output is:
'a': [('.hglf/large2', None, 'keep standin')],
'lfmr': [('large2', None, 'forget non-standin largefile')],
The items we put in 'newglist' are always the same as what we found in
actions['g'], so let's just put the same item into the list instead of
creating a new one.
The action lists returned from calculateupdates() (in merge.py) are
not required to be sorted. In fact, since they result from iteration
over the unordered manifest, they are unlikely to be sorted. Moreover,
some of the lists are appended to after they are returned from
manifestmerge(). The lists are instead sorted in
applyupdates(). Therefore, let's not sort the lists generated in
largefiles' overridecalculateupdates().
This was implied in issue3486, which specifically asked for subrepo support in
lfconvert. Now that lfconvert uses the convert extension internally when going
to normal files, the issue is half fixed. But now even non largefile repos
benefit when other transformations are needed.
Supporting a full subrepo tree conversion from a single command doesn't seem
reasonable, given the number of options that can be provided, and the
transformations that would need to occur when entering a subrepo (consider
'filemap' paths). Instead, this allows the user to incrementally convert each
hg subrepo from bottom up like so:
# so convert knows the dest type when it sees a non empty dest dir
$ hg init converted
$ hg convert orig/sub1 converted/sub1
$ hg convert orig/sub2 converted/sub2
$ hg convert orig converted
This allows different options to be applied to different subrepos more readily.
It assumes the shamap is in the default location in each converted subrepo for
simplicity. It also allows for a subrepo to be cloned into place, in case _it_
doesn't need a conversion. I was able to convert away from using
largefiles/bfiles in several subrepos with this mechanism.
Previously, if there were any hidden changesets, the --lfa argument would cause
the command to abort with a hint about using --hidden when it tripped over a
hidden changeset.
The ui object can take care of its progress object logic by itself.
test-subrepo-recursion is modified because it is a bit sensitive to the "no
progress bar" default. It will become unnecessary in the next step when
progress will be on by default in core.
The use of a singleton for all of progress handling is debatable (because
config may vary). However this is how the extension has been doing it so far.
We move that code into the ui module because this is where is should belong when
progress is moved into core.
We were wrapping the ui class again and again (uisetup, reposetup,
subrepo setup, remote repo setup, etc). We now avoid that. This has
impact on tests that were double-printing data because of this.
The monkey patching in cat() can't be fixed, because it still delegates to the
original bad(). Overriding commands.cat() should go away in favor overriding
cmdutil.cat() anyway, and that matcher can be wrapped with matchmod.badmatch().
This is suboptimal as the user still has to explicitly cancel the
histedit afterwards, but it prevents the immediate problem.
histedit should probably implicitly do 'hg histedit --abort' if a
util.Abort is raised internally.
No known issues with the previous code since it restored the original method,
but this is cleaner.
The monkey patching in cat is harmless, because it is created locally, and
doesn't pass it anywhere (subrepo cat isn't supported with largefiles).
The phrase "cannot edit immutable changeset" is kind of tautological.
Of course unchangeable things can't be changed. We instead mention
"public" and provide a hint so that we can point to the actual
problem. Even in cases where some operation other than edition cannot
be performed, "public" gives the root cause that results in the
"immutable" effect.
There is a precedent for saying "public" instead of "immutable", for
example, in `hg commit --amend`.
Retain old label as well for backwards compatibility.
Today, the terms 'active' and 'current' are interchangeably used throughout the
codebase in reference to the active bookmark (the bookmark that will be updated
with the next commit). This leads to confusion among developers and users.
This patch is part of a series to standardize the usage to 'active' throughout
the mercurial codebase and user interface.
The logic in the convert extension is more advanced, supporting extra features
like converting revision IDs in 'extras' (e.g. 'amend_source'), supports
updating hashes in commit messages, and outputs an SHA map file. Rather than
try to duplicate all of that, just use the existing code.
Even though the convert extension supports user supplied options like filemap,
etc, those features aren't available on the lfconvert interface. Therefore, it
is safe to use the filemap mechanism (in memory) to handle the standin -> file
rename. The convert extension handles the destination locking for this path.
There was a comment in test-lfconvert.t about the hash on rev 5 being different
because it was doing a better job than "hg remove" + "hg merge" + "hg commit".
It isn't clear to me what was happening or why, but now the hashes match the
original repo exactly after a roundtrip, which seems like a good idea. If there
really was something beneficial about the previous behavior, perhaps merge can
be changed so that everyone benefits.
Converting to a largefiles repo still uses the original (limited) lfconvert
logic.
The choice between the "always" case and the other case is done in
getstandinmatcher() and the next patch will change how it's determined
based on the matcher, so let's prepare by passing in the matcher, not
just the matcher's files.
Before this patch, hg record was running hg commit -i, therefore with the
experimental.crecord=True flag, hg record was actually launching the curses
record interface. Some of our users could be confused by that.
This patch makes the hg record command set this flag to False, ensuring that
hg record never shows the curses interface.
commit -i, shelve -i and revert -i remain unchanged and use the curses
interface if the experimental.crecord flag is set.
Extension authors (notably at companies using hg) have been
cargo-culting the `testedwith = 'internal'` bit from hg's own
extensions, which then defeats our "file bugs over here" logic in
dispatch. Let's be more aggressive about trying to give extension
authors a hint about what testedwith should say.
It's annoying having to specify --list and --patch/--stat when all you
really want to do is to dump a patch. This creates an explicit
--patch/--stat command that is executed if --list is not specified. It
ensures that 1) there is only one shelf name specified and 2) that the
shelf exists. Then it redirects to the original listcmd code.
Previously, mq used the force flag to allow empty commits. Now that we have
ui.allowemptycommit let's switch to that instead. We can't completely remove the
force flag since it is used for a bunch of other behavior in localrepo.commit.
Before this patch, "rebase.concludenode()" uses "dirstate.invalidate()"
as a kind of "restore .hg/dirstate to the original status" during a failure.
But it just discards changes in memory, and doesn't actually restore
".hg/dirstate". Then, it can't work as expected, if "dirstate.write()"
is executed while processing.
This patch uses "dirstateguard" instead of "dirstate.invalidate()" to
restore ".hg/dirstate" during a failure even if "dirstate.write()" is
executed before a failure.
This patch also removes "beginparentchage()" and "endparentchange()",
because "dirstateguard" makes them useless.
This is a part of preparations to fix the issue that the recent (in
memory) dirstate isn't visible to external processes (e.g. "precommit"
hook).
After this patch, the changed dirstate becomes visible to external
"precommit" hooks during "hg rebase" in "test-largefiles-misc.t",
because "dirstateguard()" writes it out. But this content isn't yet
correct, because:
- "normal3" should be marked as "A"(dded) at committing
It is newly added in the changeset being rebased.
- but it is marked as "M"(odified)
The result of "repo.setparents()" after "dirstateguard()" isn't
yet written out before "precommit". So, merging is still in
progress for "hg status" in it.
This causes marking the file newly added on "other" branch as "A".
This will be fixed by subsequent patch.
Before this patch, "mq.queue.refresh()" uses "dirstate.invalidate()"
as a kind of "restore .hg/dirstate to the original status" during a failure.
But it just discards changes in memory, and doesn't actually restore
".hg/dirstate". Then, it can't work as expected, if "dirstate.write()"
is executed while processing.
This patch uses "dirstateguard" instead of "dirstate.invalidate()" to
restore ".hg/dirstate" during a failure even if "dirstate.write()" is
executed before a failure.
This patch also removes "beginparentchage()" and "endparentchange()",
because "dirstateguard" makes them useless.
This is a part of preparations to fix the issue that the recent (in
memory) dirstate isn't visible to external processes (e.g. "precommit"
hook).
Before this patch, "mq.queue.apply()" uses "dirstate.invalidate()" as
a kind of "restore .hg/dirstate to the original status" during afailure.
But it just discards changes in memory, and doesn't actually restore
".hg/dirstate". Then, it can't work as expected, if "dirstate.write()"
is executed while processing.
This patch uses "dirstateguard" instead of "dirstate.invalidate()" to
restore ".hg/dirstate" at failure even if "dirstate.write()" is
executed before failure.
This is a part of preparations to fix the issue that the recent (in
memory) dirstate isn't visible to external processes (e.g. "precommit"
hook).
This is related to df069d92be27, but not required for that to function correctly
because 'prefix' always ends with '/', so os.path.join(prefix, _path) simply
concatenates the strings. Take the opportunity to drop the os.path usage, and
avoid confusion by using the same pattern as the overridden subrepo method.
Today, the terms 'active' and 'current' are interchangeably used throughout the
codebase in reference to the active bookmark (the bookmark that will be updated
with the next commit). This leads to confusion among developers and users.
This patch is part of a series to standardize the usage to 'active' throughout
the mercurial codebase and user interface.
Today, the terms 'active' and 'current' are interchangeably used throughout the
codebase in reference to the active bookmark (the bookmark that will be updated
with the next commit). This leads to confusion among developers and users.
This patch is part of a series to standardize the usage to 'active' throughout
the mercurial codebase and user interface.
Today, the terms 'active' and 'current' are interchangeably used throughout the
codebase in reference to the active bookmark (the bookmark that will be updated
with the next commit). This leads to confusion among developers and users.
This patch is part of a series to standardize the usage to 'active' throughout
the mercurial codebase and user interface.
It deserves more than a debug message. Show a note like:
updating mq patch p0.patch to 5:9ecc820b1737
The message could also refer to "qrefresh" instead. Same same.
Show status messages while rebasing, similar to what graft do:
rebasing 12:2647734878ef "fork" (tip)
This gives more context for the user when resolving conflicts.
When merging and the remote has turned a normal file into a largefile
and the user chooses to keep the local largefile, we use the 'r'
action for the remote largefile standin. This is wrong, since that
file does not exist in the parent of the working copy. Use 'k', which
does nothing but debug logging, instead.
When merging and the remote has turned a largefile into a normal file
and the user chooses to keep the local largefile, we use the 'r'
action for the remote normal file. This is wrong, since that file does
not exist in the parent of the working copy. Use 'k', which does
nothing but debug logging, instead.
Revtodo happens to share its value with nullrev, but this is an implementation
details, so we move away from it.
After this changeset one can successfully change the values for all
the constants and the tests still pass, but doing so would require more
refactoring if we want to avoid breaking backward compatibility on the
state file.
The state mapping is using '-1' to mark revisions that have not been
rebased yet. We introduce and use a constant for that purpose. This
will help emphasize the fact the value means something other than
nullrev.
When set to true, this option will make patchbomb always ask for confirmation
before sending the email. Confirmation is a powerful way to prevent stupid
mistakes when the sending patches.
This should let me get rid of my global alias adding
--confirm to hg email.
I know that some people may get bitten when moving from a machine with confirm
configured to a machine where it is not, but I think it is worth the risk.
This option allows the user to control the default behavior for
including an introduction message. This avoids having to tirelessly
skip the intro for people contributing to Mercurial.
The three possibles values are:
- always,
- auto (default, current behavior),
- never.
I was thinking of ("true", "false", "") (empty value being auto) but I ruled it
out as too confusing.
This new config option reuses the pre-existing 'patchbomb' section.
In c69fe5519c86 (largefiles: don't show largefile/normal prompts if
one side is unchanged, 2014-12-01), overridecalculateupdates() started
checking for false modify/delete conflicts in large files and their
standins. Then, in the very next changeset, 99b29d2bd5ed (merge:
before cd/dc prompt, check that changed side really changed,
2014-12-01), calculateupdates() itself started checking for false
modify/delete conflicts in all files. Since "large files and their
standins" is a subset of "all files", we can now drop the checks in
overridecalculateupdates().
In overridecalculateupdates(), 'g' (get) actions may be converted into
other actions. In most of these cases, it does not make sense to keep
the action's message. For example, 'remote created' does not make
sense for an 'r' (remove) action.
The message in the action is used for debugging and should not be the
same as the question presented to the user. Use a different variable
for the user message, so the 'msg' variable already in scope does not
get overwritten.
The notify output doesn't seem to be parseable anyway, what with the maxdiff
config option. Plus it is designed mainly for servers where hopefully the
admins are doing sensible things.