Add missing calls to close() to many places where files are
opened. Relying on reference counting to catch them soon-ish is not
portable and fails in environments with a proper GC, such as PyPy.
We can't assume that all pushable patches early in the series have already been
applied. If a hg qselect is done while you already have patches applied, some
patches with guards may now be pushable, even though they come earlier in the
series.
So instead of checking only applied patches, explicitly check where we are in
the series against the position of the patch we want to qpush to.
Some extensions (e.g. hgsubversion) completely override push command. Because
extensions load order is unspecified, if hgsubversion loads before mq, mq
checks about not pushing applied patches will be bypassed. Short of finding a
way to fix load order, extracting the checking logic will allow
hgsubversion-like extensions to run the check themselves.
* parse branch and nodeid header lines
* remember the line number where diffs started
Combined, these make mq.patchheader() very useful for parsing and
preserving a patch header through edits. TortoiseHg will use the
nodeid and parent to display these header datums in the graph when
patches are unapplied, and uses diffstartline to parse patch files
using record.parsepatch().
This patch prevents MQ from creating an inconsistent subrepo state. If
the .hgsub file has been changed, and none of the subrepos have
uncommitted changes, creating or updating a patch (using qnew, qrefresh,
or qrecord) will update .hgsubstate accordingly.
If any subrepos _do_ have uncommitted changes, qnew/qrefresh/qrecord
will abort.
Thanks to pmezard for proposing this solution.
If MQ allows modifying .hgsub or .hgsubstate in a patch, it can easily
lead to an inconsistent subrepo state. This patch prevents qrefresh from
adding any modifications to .hgsub or .hgsubstate to a patch. The user
is warned that these files are not included in the patch.
The tests test both the slightly irrational and the pathological cases.
This patch adds an '--exact/-e' option to qpush that will try to push the
patches in the correct location in the DAG. Specifying this option does the
following:
* If --move is specified, abort. It makes no sense to move a patch to the front
of the queue and try to apply it to its parent, because its parent is one of
the patches we just moved it in front of!
* If patches are already applied, abort. We don't want patch changesets
scattered throughout the DAG.
* If local changes are present, abort unless --force is used, as usual.
* Find the first patch we're going to push (if we're pushing multiple patches
with a target or --all).
* If that patch doesn't have a parent, abort, obviously.
* If the parent doesn't exist in the repo, abort. Something is wrong.
* Update to the parent, then continue pushing the patches as normal.
The code eventually converts data through sets to ensure unicity:
do it earlier to allow faster __contains__ lookups and avoid
`del l[l.index(x)]` kind of code.
When using a versioned patch repository, you would get a spurious
warning when deleting and adding the same patch.
Before:
$ hg qdelete --keep 3.diff
$ hg qimport --existing 3.diff
adding 3.diff to series file
3.diff already tracked!
After:
$ hg qdelete --keep 3.diff
$ hg qimport --existing 3.diff
adding 3.diff to series file
Some callers to patchheader.qseries returned the value
further, but pathcheader.qseries does not explicitly
return anything. It was confusing this was returned
further
--force was not necessary when passing --rev since cb494d252290, but this
behaviour is usually harmful when branch names are passed instead of explicit
revisions.
Changeset 1e63d4dee4f6 deprecated qsave and qrestore. In the
deprecating comment, users were referred to 'rebase --mq' which -- at
the time the message was written -- didn't exist. Currently, on the
default branch, rebase *does* take a '--mq' option, but it probably
doesn't do what Dirkjan expected it to do when he wrote the message.
In the original, deprecating commit, little context was provided as to
why this change was made. Based on my recollection, concensus at the
Paris Sprint in February 2010 was that one of the problems with MQ was
that it exposed far too many commands. Notable among these were qsave
& qrestore: very few core developers understood what they did and even
fewer (none, IIRC) actually used them. However, they couldn't be
removed; not only do the usual backwards compatibility reasons apply,
but the hg book refers to them.
Configuration from the outer repo is inherited to the patches repo when --mq is
used.
In case the patches repo only has paths.default configured but the outer repo
has paths.default-push then the inherited default-push will win. Very
confusing.
Inheriting the default paths is however wrong in all sane cases, so now we
explicitly remove them.
qqueue --delete only deletes the reference to the queue, and leaves
the associated patch directory behind. There is no Mercurial-way of
getting rid of that patch directory afterward.
This patch adds the --purge option to qqueue, that deletes the queue
from the list, and also removes the associated patch dir. If the queue
was non-existant, but the patch dir was, it is removed nonetheless.
This is to avoid manual intervention in the .hg directory.
Currently, if you start editing a commit message from qrefresh -e and, for any
reason: forget you were editing it, leave the editor open and start qpopping
and qpushing, when you decide to save your commit message, it is going to fail.
This patch copies the commit behavior of saving the message contents in
$HGROOT/.hg/last-message.txt before continuing.
For scripting purposes, it can be convenient to get a simple listing of
available queues, without indication of the active one.
--quiet documentation change removed by Patrick Mézard.
Before this change, the command would abort with a not too clear "patch
renametothis does not exist" error.
This change makes:
qimport --existing --name renametothis thatexistingpatch
equivalent to:
qimport --existing thatexistingpatch; qrename thatexistingpatch renametothis
stripping of applied mq patches leads to wrong state recorded in status
file. find all mq patches that will be affected and clean up status file
before strip.
9af52509546a caused that we find the index of the moving patch in self.series
but look it up in self.full_series. The difference between these is that
full_series also contains comment lines, and we thus moved the wrong patch.
Use back self.full_series to find the moving patch, but take care of striping
the patch guard markers before comparing the patch name. Test cases have been
added for comments and empty lines in self.full_series, and for the case of
guarded patches.
Original patch contributed by Mads Kiilerich <mads@kiilerich.com>
It seems wiser to reset mq.added at the end of the mq transaction instead of at
the beginning of a qimport call: this way, calling several times qimport()
without saving mq state in-between does not overwrite the previous value of
mq.added (this happens, for example in rebase, where we import several patches
in a batch before calling .save_dirty() )
MQ patch name can contain slashes, e.g. 'foo/bar.patch'.
Currently "qnew foo/bar.patch" works, but
"qrename foo/bar.patch new/dir.patch" fails with
"No such file or directory".
Also added test case for "qnew foo/bar.patch"
In the case of guarded patch, the patch could not be found because the
full_series list contains also the guard value appended to each patch name.
As we already checked that the patch is pushable above in the code, we just
have to use the series list (which doesn't contains guard value) to get the
patch index.
this helps users to know what kind of option is:
- no value is required(flag option)
- value is required
- value is required, and multiple occurrences are allowed
each kinds are shown as below:
-f --force force push
-e --ssh CMD specify ssh command to use
-b --branch BRANCH [+] a specific branch you would like to push
if one or more 3rd type options are shown, explanation for '[+]' mark
is also shown as footnote.
Some implementations of ui.label() (HTML versions in particular) must escape
the provided text and then markup the text with their tags. When this marked
up text is then passed to ui.write(), we must label the text as 'ui.labeled'
so the implementation knows not to escape it a second time (exposing the initial
markup).
This required the addition of a 'ui.plain' label for text that is purposefully
not marked up.
I was a little pedantic here, passing even ' ' strings to ui.label() when it
would be included with other labeled text in a ui.write() call. But it seemed
appropriate to lean to the side of caution.
Each check is moved under the code handling the relevant option, and
a new one is added for --create. This fixes duplicated entries being
added to the queues list.
Compare this to --force which allows anything to be pushed. With --new-branch,
only changesets to named branches not present on the and changesets not
introducing additional heads on existing branches are allowed.
Developed by
Henrik Stuart <henrik.stuart@edlund.dk>
Sune Foldager <cryo@cyanite.org>
`opts['unified'] = '0'` tries to reduce the number of lines to be
processed by patch.diffstat, but here it does not affect diffopts,
thus it does not make sense.
Instead, we can change `diffopts.context` directly.
Added test case for qdiff --stat.
All callers to localrepo.transaction() must supply a transaction description.
The description and the existing repository tip are then stored
(transactionally) into .hg/undo.desc; where rollback can later find it.
If, on Windows, your repository and working copy are in a reparse point and you
use os.removedirs, you will remove non-empty reparse points, disabling the
reparse point. See @6b1369445b7b.
By overriding ui.write(), ui.write_err(), ui.popbuffer(), and ui.label(),
the color extension can avoid parsing command output and simply colorize
output based on labels.
As before, the color extension provides a list of default colors for
core commands/labels. Other extensions can provide their own defaults by
specifying a colortable dict (similar to cmdtable).
In this process, --color is promoted to a global option and the deprecated
--no-color option is removed.
Since norepo is a string, not a list, the norepo check was matching
command names against any substring in norepo. This fix splits norepo
into a list of commands.
Without -c, it is a no-op (the queue is implicitly initialized by all
relevant commands if needed), and queue repositories with -c are an
advanced usage of mq, and not otherwise required.
The goal of this patch is to add the IDs of the parents of applied MQ patches
into the patch file headers whenever qnew or qrefresh are run.
This will serve as a reminder of when the patches last applied cleanly and
will let us do more intelligent things in the future, such as:
* Resolve conflicts found when qpushing to a new location by merging
instead of simply showing rejects.
* Display better diffs of versioned MQ patches because we can tell how the
patched files have changed in the meantime.
Here are the new rules this patch introduces. They are checked in this order:
* If a patch currently has old, plain-style patch headers ("From:" and
"Date:") do not change the style or add any new headers.
* If the 'mq.plain' configuration setting is true, only plain-style
headers will be used for all MQ patches.
* qnew will initialize new patches with HG-style headers and fill in the
"# Parent" header with the appropriate parent node.
* qrefresh will refresh the "# Parent" header with the current parent of
the current patch.
The slow path/fast path distinction has existed since mq was added to Mercurial
in 2006. The slow path was used whenever the refreshed revision wasn't the tip
We should not translate the "imported patch" message. The translated message
confuses the detection whether the user has not updated the commit message yet.
We try to avoid to translate generated commit messages.
We need to do this to avoid file/directories conflicts.
This causes patches removing a committed file and replacing it
with a directory to be "unpoppable".
Since it only changes the working directory, it does not matter whether a patch is
applied. This change makes it easier to use hg import --no-commit instead of patch.
This fixes an incompatibility with patch(1), which also uses --reverse
for reversed diffs. The --inverse flag was added in 0f0383897d54. That
name was chosen over --reverse since it was thought that --reverse
would make --rev ambiguous.
It turns out that both flags can co-exist, with the cost that --rev
can no longer be shortened to --r and --re. Since one can always use
the short -r option, this is not a real problem.
After changeset 54b67f7bd5df, ui.username will abort by default if no
username is set. It is therefore wrong to call ui.username when a
username was provided on the command line.
Most of the time, one can reverse a diff by swapping the revisions passed with
-r but it happens that if you use the global -R, and diff against the tip of
the current repo, you can't swap the revisions. One use-case for that is
reviewing changes from a bundle before unbundling. One could also pipe the
output of `hg diff` to a command line filter that reverses the diff, but that
would remove the benefit from color diffs. Therefore, having an option in
`hg diff` to reverse a diff is a good thing.
The option flag selection was tricky. GNU patch uses -R/--reverse but -R is
already used as a global option and --reverse would make --rev ambiguous.
Normally, diffs without any text insertions or deletions are reported
as having 0 lines changed by stock diffstat. Compatibility is
preserved with stock diffstat in this case, but when using --git,
binary files are marked with Bin as a means of clarification.
git diff --stat does something similar, though it also includes the
old and new file sizes.
diff/qdiff --stat invokes patch.diffstat() on the diff output.
When in interactive mode, the output's maximum width is determined by the
terminal's width.