Mercurial > evolve
changeset 3418:85cdce113c2c mercurial-4.3
test-compat: merge stable into mercurial-4.3
line wrap: on
line diff
--- a/.hgignore Sat Dec 16 23:40:39 2017 +0100 +++ b/.hgignore Tue Jan 16 04:35:34 2018 +0100 @@ -14,3 +14,11 @@ ^docs/tutorials/.*\.rst$ \.ico$ tests/\.testtimes + +^docs/training/graphs/ +^docs/training/html/ +^docs/training/index.html +^docs/training/graphviz-images/ +^docs/training/img/ +^docs/training/output/ +^docs/training/pandocfilters/
--- a/CHANGELOG Sat Dec 16 23:40:39 2017 +0100 +++ b/CHANGELOG Tue Jan 16 04:35:34 2018 +0100 @@ -1,12 +1,33 @@ Changelog ========= -7.1.1 - in progress +7.2.0 -- 2018-01-15 ------------------- -topic (0.6.1) + * evolve: changes to the on disk format for interrupted evolve + * evolve: --continue now propertly preserve phase information (issue5720) + * evolve: --continue now properly reports merges as evolve + * commit: suggest using topic on new heads + * uncommit: `--revert` flag added to clean the wdir after uncommit + * obslog: add color support to content-diff output with --patch + * fix `hg prev` behavior on obsolete changesets + * no longer issues "obsolete working copy" message during no-op + + * use the new instabilities names from mercurial 4.4+ + (in `hg evolve --list` and other messages) + + * new algorithm for obshashrange discovery: + + The new algorithm is faster, simpler to cache and with better complexity. It + is able to handle repository of any size (naive python implementation is a + bit slow). Support for the previous experimental approach have been + dropped, please update both clients and servers. The new approach is still + hidden behind and experimental flag for now. + +topic (0.7.0) * fix compatibility with Mercurial-4.3 + * new template keyword `topic` to get changesets topic 7.1.0 -- 2017-12-12 -------------------
--- a/MANIFEST.in Sat Dec 16 23:40:39 2017 +0100 +++ b/MANIFEST.in Tue Jan 16 04:35:34 2018 +0100 @@ -7,6 +7,7 @@ exclude tests/test-drop.t exclude tests/test-inhibit.t exclude tests/test-oldconvert.t +exclude docs/tutorial/.netlify include COPYING include docs/figures/hgview-example.png include docs/makefile @@ -17,6 +18,7 @@ include docs/tutorials/*.t include hgext3rd/__init__.py include hgext3rd/evolve/*.py +include hgext3rd/evolve/thirdparty/*.py include hgext3rd/topic/*.py include hgext3rd/topic/README include MANIFEST.in @@ -27,5 +29,13 @@ include tests/*.sh include tests/testlib/*.sh include tests/*.t +recursive-include docs/tutorial *.rst +recursive-include docs/tutorial *.css +include docs/tutorial/standalone.html +recursive-include docs/tutorial *.js +recursive-include docs/tutorial *.md +recursive-include docs/tutorial *.py +recursive-include docs/tutorial *.sh +recursive-include docs/tutorial *.t prune debian recursive-include docs/figures *.svg
--- a/debian/changelog Sat Dec 16 23:40:39 2017 +0100 +++ b/debian/changelog Tue Jan 16 04:35:34 2018 +0100 @@ -1,3 +1,9 @@ +mercurial-evolve (7.2.0) UNRELEASED; urgency=medium + + * new upstream release + + -- Pierre-Yves David <pierre-yves.david@ens-lyon.org> Mon, 15 Jan 2018 21:44:57 +0100 + mercurial-evolve (7.1.0-1) unstable; urgency=medium * new upstream release
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/.netlify Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,1 @@ +{"site_id":"cf023865-0eb1-49e9-951b-29555949abf0","path":"html/"} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/README.rst Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,63 @@ +============================= +Training supports +============================= + +Contributing +============ + +The main source for the supports is the `slides.md` but it doesn't contains +all the source. + +The `slides.md` file contains several snippets that are replaced by other +files at compilation time. + +For example: + +.. code:: markdown + + ~~~raw-file + output/fix-a-bug-base.log + ~~~ + +Will replace this three lines by the content of the file `output/fix-a-bug- +base.log` which is generated when running the .t test file (see below for +instruction how to do that). + +.. code:: markdown + + ~~~graphviz-file + graphs/fix-bug-1.dot + ~~~ + +Will replace this three lines by the svg rendering of the graphviz definition +in the file `graphs/fix-bug-1.dot`. This file is generated when running the .t +test file (see below for instruction how to do that). + + +Environment preparation +======================= + +This training supports needs pandoc to compile. + +You'll need a copy of the Mercurial source in order to generate the training +supports. + +You will also needs a functioning Python environment with the possibility to +use `pip install` with your current user. In doubt, you can use a `virtualenv +<https://virtualenv.pypa.io/en/stable/>`. + +You can then run the `prepare.sh` script that will configure the environment +for you. + +Generating the supports +======================= + +First, you need to run a .t test file to generate a bunch of files. You can +run the test file with this command: + +`python /PATH/TO/MERCURIAL/tests/run-tests.py -l test-training.t` + +It should have generated files in at least two directories: `graphs` and +`output`. + +Finally, launch the `compile.sh` to generate the `index.html` output file.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/compile.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,16 @@ +#!/bin/bash +set -eox pipefail + + +function compile { + pandoc \ + -s $1 \ + -o $2 \ + --toc --toc-depth=4 \ + -F pandocfilters/examples/graphviz.py -F mypandocfilters/graphviz-file.py -F mypandocfilters/raw-file.py \ + -t html5 \ + --template standalone.html --variable=template_css:uikit.css + +} + +compile slides.md index.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/deploy.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,9 @@ +mkdir -p html + +cp index.html html/ +cp *.css html/ +cp *.js html/ +cp -R img html/ +cp -R graphviz-images/ html/ + +netlify deploy
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/draft.md Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,1288 @@ +--- +author: Boris Feld <boris.feld@octobus.net> +title: Changeset evolution +date: June 23, 2017 +--- + +# Why Evolve is the future? (TO CHANGE) + +Use hexagon or drop all of themes +Use old names +Replace hg amend by commit --amend + +Flow + +Basic - Feature - Tool / instability - command semantic + +Basic (local amend + local rebase) + +Stabilization -> Evolution + +Feature + +# Local amend + +## Amending commits + +We all makes mistake: + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fx bug[case"; + } +~~~ + +## Some times pass + +## Urgent Amend needed + +But it's easy to fix the fix: + +~~~ {.sh} +hg commit --amend -m "Fix bug" +~~~ + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + } +~~~ + +## So easy to do something wrong + +But wait you had local changes! And they get incorporated into the amend. + +## Too bad + +It's too late, they are gone! + +<img src="https://media1.giphy.com/media/vMiCDfoKdJP0c/giphy.gif"> + +## HARD + +UNbundle, get the rev, strip + +## Never without Evolve! + +<img src="https://media3.giphy.com/media/EVbEdEW3kuu0o/giphy.gif"> + + +## Let's try again! + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fx bug"; + } +~~~ + +## Evolve powa + +With evolve this time: + +~~~ {.sh} +hg commit --amend -m "Fix bug" +~~~ + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + } +~~~ + +## Ok what the difference? + +<pre class="shell_output"> +$> hg log -G +@ <span style="color:olive;">changeset: 3:467de638a224</span> +| tag: tip +| parent: 0:852811e0e2a8 +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:15:55 2017 +0200 +| summary: Fix bug +| +o <span style="color:olive;">changeset: 0:852811e0e2a8</span> + user: Boris Feld <boris.feld@octobus.net> + date: Wed Jun 21 14:15:55 2017 +0200 + summary: Root + +</pre> + +## The difference + +<pre class="shell_output"> +$> hg log -G --hidden +@ <span style="color:olive;">changeset: 3:467de638a224</span> +| tag: tip +| parent: 0:852811e0e2a8 +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:15:55 2017 +0200 +| summary: Fix bug +| +| x <span style="color:olive;">changeset: 2:614cb09cc83d</span> +| | user: Boris Feld <boris.feld@octobus.net> +| | date: Wed Jun 21 14:15:55 2017 +0200 +| | summary: temporary amend commit for e46245132d3d +| | +| x <span style="color:olive;">changeset: 1:e46245132d3d</span> +|/ user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:15:55 2017 +0200 +| summary: Fx bug +| +o <span style="color:olive;">changeset: 0:852811e0e2a8</span> + user: Boris Feld <boris.feld@octobus.net> + date: Wed Jun 21 14:15:55 2017 +0200 + summary: Root + +</pre> + +## Perf impact + +No strip == no cache bust, == faster + +# Local rebase + +## You are working on your branch + +~~~graphviz + digraph G { + rankdir="LR"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=feature]; + Parent -> "Feature"; + } +~~~ + +## More work + +~~~graphviz + digraph G { + rankdir="LR"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=feature]; + Parent -> "Feature" -> "Feature 2"; + } +~~~ + +## Pull + +~~~graphviz + digraph G { + rankdir="LR"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Trunk" -> "Trunk 2"; + + node[group=feature]; + Parent -> "Feature" -> "Feature 2"; + } +~~~ + +## Time to rebase + +~~~graphviz + digraph G { + rankdir="LR"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Trunk" -> "Trunk 2"; + + node[group=feature]; + "Trunk 2" -> "Feature" -> "Feature 2"; + } +~~~ + +## Without evolve + +<pre class="shell_output"> +@ <span style="color:olive;">changeset: 6:105f743d81c8</span> +| tag: tip +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:47:48 2017 +0200 +| summary: Feature2 +| +o <span style="color:olive;">changeset: 5:3966a515e569</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:47:48 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 4:bd3d94325819</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:47:49 2017 +0200 +| summary: Trunk2 +| +o <span style="color:olive;">changeset: 3:120d3e4ce8b7</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:47:49 2017 +0200 +| summary: Trunk +| +o <span style="color:olive;">changeset: 2:36db121866a2</span> +| user: Boris Feld <boris.feld@octobus.net> +~ date: Wed Jun 21 14:47:48 2017 +0200 + summary: Parent + +</pre> + +## With evolve + +<pre style="font-size: 0.25em !important;"> +@ <span style="color:olive;">changeset: 10:2c1a992b87c3</span> +| tag: tip +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature2 +| +o <span style="color:olive;">changeset: 9:751113c206d0</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 8:9f9f3db01630</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Trunk2 +| +o <span style="color:olive;">changeset: 7:a5e9a3060e20</span> +| parent: 4:32253567b531 +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Trunk +| +| x <span style="color:olive;">changeset: 6:a57f1852d740</span> +| | branch: feature +| | user: Boris Feld <boris.feld@octobus.net> +| | date: Wed Jun 21 14:50:39 2017 +0200 +| | summary: Feature2 +| | +| x <span style="color:olive;">changeset: 5:896dc0771e5e</span> +|/ branch: feature +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 4:32253567b531</span> +| user: Boris Feld <boris.feld@octobus.net> +~ date: Wed Jun 21 14:50:39 2017 +0200 + summary: Parent + +</pre> + +# How does it works? + +## It's smart + +<img src="https://media2.giphy.com/media/ZThQqlxY5BXMc/giphy.gif"> + +## Does Evolve only stores more changesets? (CHANGE) + +## Not only + +Remember our amend? + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fx bug"; + } +~~~ +</div> + +<div class='right' style='order:2; width: 50%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + } +~~~ +</div> +</div> + +## More revisions + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fx bug"; + } +~~~ +</div> + +<div class='right' style='order:2; width: 50%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + node[group=obsolete]; + Parent -> "Fx bug"; + } +~~~ +</div> +</div> + +## But hidden + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fx bug"; + } +~~~ +</div> + +<div class='right' style='order:2; width: 50%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Parent -> "Fx bug"; + } +~~~ +</div> +</div> + +## Here is the smartness (change word)! + +~~~graphviz + digraph G { + rankdir="BT"; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Parent -> "Fx bug"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "Fx bug" -> "Fix bug"; + } +~~~ + +## Obs markers + +Obs markers stores the relation between a changeset and its evolutions. + +XXX: Speak about META + +~~~graphviz + digraph G { + rankdir="BT"; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + node[group=obsolete, style="dotted, filled" fillcolor="#DFDFFF"]; + edge[dir=back, style=dotted, arrowtail=dot]; + "Predecessor" -> "Successor"; + + "Successor" [style="filled", fillcolor="#7F7FFF"]; + } +~~~ + + +# Phases + +## 3 phases + +Changesets can be in one of three phases: + +* Public +* Draft +* Secrets + +## Public + +The public phase holds changesets that have been exchanged publicly. + +Changesets in the public phase are expected to remain in your repository history and are said to be immutable. + +## Drafts + +The draft phase holds changesets that are not yet considered a part of the repository's permanent history. + +You can safely rewrite them. + +New commits are in the draft phase by default. + +## Secrets (hide) + +The secret phase holds changesets that you do not want to exchange with other repositories. + +Secret changesets are hidden from remote peers and will not be included in push operations. + +Manual operations or extensions may move a changeset into the secret phase. + +## Representation + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Public -> Draft -> Secret; + + Draft [shape="pentagon"]; + Secret [shape="square"]; + } +~~~ + +# Instability (add sub-titles, obsolete -> orphan, etc...) + +## Obsolete + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + + node[group=main]; + Root -> New; + node[group=obsolete]; + Root -> Obsolete; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Obsolete -> New; + + Obsolete [fillcolor="#DFDFFF"]; + Root[shape="circle"]; + } +~~~ + +## Unstable + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + node[group=main]; + Root -> New; + node[group=obsolete]; + Root -> Obsolete -> Unstable; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Obsolete -> New; + + Obsolete [fillcolor="#DFDFFF"]; + Unstable [fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +## Bumped + +## Divergent + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + Root -> Base; + Root -> Divergent1; + Root -> Divergent2; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Base -> Divergent1; + Base -> Divergent2; + + Base [shape="pentagon", fillcolor="#DFDFFF"]; + Divergent1 [fillcolor="#FF3535"]; + Divergent2 [fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +# Topic + +# CHANGE TITLE (LATER IN THE FLOW) + +## Log on obsolete + +<pre style="font-size: 0.25em;"> +$> hg log -G +o <span style="color:olive;">changeset: 10:2c1a992b87c3</span> +| tag: tip +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature2 +| +o <span style="color:olive;">changeset: 9:751113c206d0</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 8:9f9f3db01630</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Trunk2 +| +o <span style="color:olive;">changeset: 7:a5e9a3060e20</span> +| parent: 4:32253567b531 +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Trunk +| +| @ <span style="color:olive;">changeset: 6:a57f1852d740</span> +| | branch: feature +| | user: Boris Feld <boris.feld@octobus.net> +| | date: Wed Jun 21 14:50:39 2017 +0200 +| | summary: Feature2 +| | +| x <span style="color:olive;">changeset: 5:896dc0771e5e</span> +|/ branch: feature +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 4:32253567b531</span> +| user: Boris Feld <boris.feld@octobus.net> +~ date: Wed Jun 21 14:50:39 2017 +0200 + summary: Parent + +</pre> + +## Log with hidden + +<pre style="font-size: 0.25em;"> +$ hg log -G --hidden +@ <span style="color:olive;">changeset: 10:2c1a992b87c3</span> +| tag: tip +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature2 +| +o <span style="color:olive;">changeset: 9:751113c206d0</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 8:9f9f3db01630</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Trunk2 +| +o <span style="color:olive;">changeset: 7:a5e9a3060e20</span> +| parent: 4:32253567b531 +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Trunk +| +| x <span style="color:olive;">changeset: 6:a57f1852d740</span> +| | branch: feature +| | user: Boris Feld <boris.feld@octobus.net> +| | date: Wed Jun 21 14:50:39 2017 +0200 +| | summary: Feature2 +| | +| x <span style="color:olive;">changeset: 5:896dc0771e5e</span> +|/ branch: feature +| user: Boris Feld <boris.feld@octobus.net> +| date: Wed Jun 21 14:50:39 2017 +0200 +| summary: Feature +| +o <span style="color:olive;">changeset: 4:32253567b531</span> +| user: Boris Feld <boris.feld@octobus.net> +~ date: Wed Jun 21 14:50:39 2017 +0200 + summary: Parent + +</pre> + +## Obslog + +Behold our savior Obslog! + +## Obslog + +<pre class="shell_output"> +$> hg obslog -r 3 +o <span style="color:olive;">c4414d4a5955</span> <span style="color:blue;">(3)</span> Fix bug +| +x <span style="color:olive;">9b5b4aa63d51</span> <span style="color:blue;">(1)</span> Fx bug + rewritten by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> <span style="color:teal;">(Wed Jun 21 14:50:38 2017 +0200)</span> as <span style="color:olive;">c4414d4a5955</span> + +</pre> + +<pre class="shell_output"> +$> hg obslog -r 6 --all --hidden +@ <span style="color:olive;">2c1a992b87c3</span> <span style="color:blue;">(10)</span> Feature2 +| +x <span style="color:olive;">a57f1852d740</span> <span style="color:blue;">(6)</span> Feature2 + rewritten by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> <span style="color:teal;">(Wed Jun 21 14:50:39 2017 +0200)</span> as <span style="color:olive;">2c1a992b87c3</span> + +</pre> + +Obslog is your next best friend! + +## Obslog + +<img src="https://media4.giphy.com/media/LxPsfUhFxwRRC/giphy.gif"> + +# Evolve Basics behind the hood + +## Amend + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A"; + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> +To amend A: + + hg amend -m 'A1' +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A1"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A1"; + Root [shape="circle"]; + } +~~~ +</div> +</div> + +## Amend bis + +It also works with: + + hg commit --amend -m 'A1' + + +## Prune + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A"; + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> + +To prune A: + + hg prune -r "desc(A)" +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + Root [shape="circle"]; + + // Revisions + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + } +~~~ +</div> +</div> + + + +## Rebase + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> B; + node[group=main]; + Root -> "A"; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> + +In order to rebase A on top of B; + + hg rebase -r "desc(A)" -d "desc(B)" + +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> B -> "A'"; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A'"; + + Root [shape="circle"]; + } +~~~ +</div> +</div> + + +# More advanced + +## Fold + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 15%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> A -> B; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 70%'> + +To fold A and B: + + hg fold -r "desc(A)" -r "desc(B)" -m "C" + +</div> + +<div class='right' style='order:2; width: 15%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> C; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> A -> B; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "C"; + "B" -> "C"; + + Root [shape="circle"]; + } +~~~ + +</div> +</div> + + +## Split + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> A; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> + +Split in two: + + hg split -r "desc(A)" +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> B -> C; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> A; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "C"; + "A" -> "B"; + + Root [shape="circle"]; + } +~~~ +</div> +</div> + + +# Warning zone + +## Divergence + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> "A"; + + Root [shape="circle"]; + } +~~~ + +## Divergence + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 30%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> "B"; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "B"; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 70%'> + +First amend: + + hg amend -m B; + +</div> +</div> + + +## Divergence 2 + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> + +<div class="middle" style='order:1; width: 70%'> + +Second amend: + + hg amend -m C + +</div> + +<div class='left' style='order:2; width: 30%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + Root; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Revisions + node[group=branch, fillcolor="#7F7FFF", style="filled"]; + Root -> "C"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "C"; + + Root [shape="circle"]; + } +~~~ +</div> +</div> + +## Result + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + node[group=main]; + Root -> "B"; + node[group=divergence]; + Root -> "C"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + A -> B; + A -> C; + + Root [shape="pentagon"]; + B [fillcolor="#FF3535"]; + C [fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +## That's gonna hurt! + +# Stabilization + +## Stabilization with amend + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + node[group=main]; + Root -> "A'"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A" -> B; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A'"; + + B[fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +## Evolve! + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class="middle" style='order:2; width: 50%'> + +Stabilize repo: + + hg evolve --all +</div> +<div class='right' style='order:2; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + node[group=main]; + Root -> "A'" -> "B'"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A" -> B; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A'"; + "B" -> "B'"; + + Root[shape="circle"]; + } +~~~ + +</div> +</div> + +# Future is near! + +## Effect-flag + +Remember our obs-markers? + +They are great for evolution, but how do you know what changed between two evolutions? + +## Effect-flag + +Effect-flag are storing what changed between evolutions. You can view them with `obslog`, who else? + +## Effect-flag + +Does the meta only changed? + +<pre class="shell_output"> +o <span style="color:olive;">5732d5ea6aa2</span> <span style="color:blue;">(2)</span> Fix bug +| +@ <span style="color:olive;">aa3cd7ee52fc</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> <span style="color:teal;">(Wed Jun 21 15:49:54 2017 +0200)</span> as <span style="color:olive;">5732d5ea6aa2</span> + +</pre> + +## Or did the code changed? + +<pre class="shell_output"> +@ <span style="color:olive;">8f824718f3f7</span> <span style="color:blue;">(12)</span> Fix the build +| +x <span style="color:olive;">f9310b4b05e1</span> <span style="color:blue;">(10)</span> Fix the build + rewritten(content) by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> <span style="color:teal;">(Wed Jun 21 15:53:07 2017 +0200)</span> as <span style="color:olive;">8f824718f3f7</span> + +</pre> + +## Or was rebased? + +<pre class="shell_output"> +o <span style="color:olive;">ab709059df38</span> <span style="color:blue;">(9)</span> Feature2 +| +@ <span style="color:olive;">3d61cb9ab34f</span> <span style="color:blue;">(5)</span> Feature2 + rewritten(branch, parent) by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> <span style="color:teal;">(Wed Jun 21 15:53:06 2017 +0200)</span> as <span style="color:olive;">ab709059df38</span> + +</pre> + +## Obslog + +<img src="https://media0.giphy.com/media/3oriO13KTkzPwTykp2/giphy.gif"> + +## Obsfate + +<pre class="shell_output"> +o 8f824718f3f7 +| +| x f39472eb8519 +| | Obsfate: pruned by Boris Feld <boris.feld@octobus.net> (at 2017-06-21 15:53 +0200) +| | +| x f9310b4b05e1 +|/ Obsfate: rewritten by Boris Feld <boris.feld@octobus.net> as 8f824718f3f7 (at 2017-06-21 15:53 +0200) +| +o ab709059df38 +| +o b0d7c614e47d +| +o d61083b45bba +| +o 50ebd46e2452 +| +| @ 3d61cb9ab34f +| | Obsfate: rewritten by Boris Feld <boris.feld@octobus.net> as ab709059df38 (at 2017-06-21 15:53 +0200) +| | +| x 1c6a75c00a45 +|/ Obsfate: rewritten by Boris Feld <boris.feld@octobus.net> as b0d7c614e47d (at 2017-06-21 15:53 +0200) +| +o c1bdb750ab80 +| +o 39752c0e48a4 +| +| x 36744bfd9d65 +|/ Obsfate: rewritten by Boris Feld <boris.feld@octobus.net> as 39752c0e48a4 (at 2017-06-21 15:53 +0200) +| +o 7d12a4681f84 +</pre> + +## Obslog --patch + +<pre class="shell_output"> +$> hg obslog --patch +x <span style="color:olive;">19fb99aaa0d5</span> <span style="color:blue;">(3594)</span> obslog: add a patch option +| rewritten(content) by <span style="color:green;">Pierre-Yves David <pierre-yves.david@octobus.net></span> <span style="color:teal;">(Mon Jun 19 19:25:18 2017 +0200)</span> as <span style="color:olive;">81b01fe6db3b</span> +| diff -r 19fb99aaa0d5 -r 81b01fe6db3b hgext3rd/evolve/obshistory.py +| --- a/hgext3rd/evolve/obshistory.py Mon Jun 19 19:00:36 2017 +0200 +| +++ b/hgext3rd/evolve/obshistory.py Mon Jun 19 19:00:36 2017 +0200 +| @@ -105,6 +105,10 @@ +| markerfm.plain('\n') +| +| # Patch +| + +| +# XXX-review: I find it a bit hacky always call showpatch and expect it to not +| +# XXX-review: show anything without --patch. I would prefer and explicite condition for +| +# XXX-review: calling showpatch. +| self.showpatch(ctx, matchfn) +| +| self.hunk[ctx.node()] = self.ui.popbuffer() +| ... +| +| o <span style="color:olive;">a788967aa800</span> <span style="color:blue;">(3593)</span> obslog: clarify some sorting code +| | +x | <span style="color:olive;">4c2be5027b23</span> +|/ rewritten(user) by <span style="color:green;">Pierre-Yves David <pierre-yves.david@octobus.net></span> <span style="color:teal;">(Mon Jun 19 19:00:54 2017 +0200)</span> as <span style="color:olive;">19fb99aaa0d5</span> +| (No patch available yet, context is not local) +| +x <span style="color:olive;">5d04c9bfac7e</span> +| rewritten(description, user, date, parent, content) by <span style="color:green;">Pierre-Yves David <pierre-yves.david@octobus.net></span> <span style="color:teal;">(Mon Jun 19 19:00:36 2017 +0200)</span> as <span style="color:olive;">4c2be5027b23, a788967aa800</span> +| (No patch available yet, context is not local) +| +x <span style="color:olive;">8ddfd687cf57</span> <span style="color:blue;">(3559)</span> obslog: add a patch option +| rewritten(parent) by <span style="color:green;">Pierre-Yves David <pierre-yves.david@octobus.net></span> <span style="color:teal;">(Mon Jun 19 18:59:02 2017 +0200)</span> as <span style="color:olive;">5d04c9bfac7e</span> +| (No patch available yet, succ is unknown locally) +| +x <span style="color:olive;">27d388000e90</span> <span style="color:blue;">(3541)</span> obslog: add a patch option + rewritten(content) by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> <span style="color:teal;">(Mon Jun 19 18:40:16 2017 +0200)</span> as <span style="color:olive;">8ddfd687cf57</span> +</pre> + + +# Conclusion + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G{} +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> +To stuff: + + hg +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G{} +~~~ +</div> +</div>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/jquery.sticky-kit.js Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,251 @@ +// Generated by CoffeeScript 1.9.2 + +/** +@license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net + */ + +(function() { + var $, win; + + $ = this.jQuery || window.jQuery; + + win = $(window); + + $.fn.stick_in_parent = function(opts) { + var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, parent_selector, recalc_every, sticky_class; + if (opts == null) { + opts = {}; + } + sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming; + if (offset_top == null) { + offset_top = 0; + } + if (parent_selector == null) { + parent_selector = void 0; + } + if (inner_scrolling == null) { + inner_scrolling = true; + } + if (sticky_class == null) { + sticky_class = "is_stuck"; + } + doc = $(document); + if (enable_bottoming == null) { + enable_bottoming = true; + } + fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { + var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; + if (elm.data("sticky_kit")) { + return; + } + elm.data("sticky_kit", true); + last_scroll_height = doc.height(); + parent = elm.parent(); + if (parent_selector != null) { + parent = parent.closest(parent_selector); + } + if (!parent.length) { + throw "failed to find stick parent"; + } + fixed = false; + bottomed = false; + spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); + if (spacer) { + spacer.css('position', elm.css('position')); + } + recalc = function() { + var border_top, padding_top, restore; + if (detached) { + return; + } + last_scroll_height = doc.height(); + border_top = parseInt(parent.css("border-top-width"), 10); + padding_top = parseInt(parent.css("padding-top"), 10); + padding_bottom = parseInt(parent.css("padding-bottom"), 10); + parent_top = parent.offset().top + border_top + padding_top; + parent_height = parent.height(); + if (fixed) { + fixed = false; + bottomed = false; + if (manual_spacer == null) { + elm.insertAfter(spacer); + spacer.detach(); + } + elm.css({ + position: "", + top: "", + width: "", + bottom: "" + }).removeClass(sticky_class); + restore = true; + } + top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; + height = elm.outerHeight(true); + el_float = elm.css("float"); + if (spacer) { + spacer.css({ + width: elm.outerWidth(true), + height: height, + display: elm.css("display"), + "vertical-align": elm.css("vertical-align"), + "float": el_float + }); + } + if (restore) { + return tick(); + } + }; + recalc(); + if (height === parent_height) { + return; + } + last_pos = void 0; + offset = offset_top; + recalc_counter = recalc_every; + tick = function() { + var css, delta, recalced, scroll, will_bottom, win_height; + if (detached) { + return; + } + recalced = false; + if (recalc_counter != null) { + recalc_counter -= 1; + if (recalc_counter <= 0) { + recalc_counter = recalc_every; + recalc(); + recalced = true; + } + } + if (!recalced && doc.height() !== last_scroll_height) { + recalc(); + recalced = true; + } + scroll = win.scrollTop(); + if (last_pos != null) { + delta = scroll - last_pos; + } + last_pos = scroll; + if (fixed) { + if (enable_bottoming) { + will_bottom = scroll + height + offset > parent_height + parent_top; + if (bottomed && !will_bottom) { + bottomed = false; + elm.css({ + position: "fixed", + bottom: "", + top: offset + }).trigger("sticky_kit:unbottom"); + } + } + if (scroll < top) { + fixed = false; + offset = offset_top; + if (manual_spacer == null) { + if (el_float === "left" || el_float === "right") { + elm.insertAfter(spacer); + } + spacer.detach(); + } + css = { + position: "", + width: "", + top: "" + }; + elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); + } + if (inner_scrolling) { + win_height = win.height(); + if (height + offset_top > win_height) { + if (!bottomed) { + offset -= delta; + offset = Math.max(win_height - height, offset); + offset = Math.min(offset_top, offset); + if (fixed) { + elm.css({ + top: offset + "px" + }); + } + } + } + } + } else { + if (scroll > top) { + fixed = true; + css = { + position: "fixed", + top: offset + }; + css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; + elm.css(css).addClass(sticky_class); + if (manual_spacer == null) { + elm.after(spacer); + if (el_float === "left" || el_float === "right") { + spacer.append(elm); + } + } + elm.trigger("sticky_kit:stick"); + } + } + if (fixed && enable_bottoming) { + if (will_bottom == null) { + will_bottom = scroll + height + offset > parent_height + parent_top; + } + if (!bottomed && will_bottom) { + bottomed = true; + if (parent.css("position") === "static") { + parent.css({ + position: "relative" + }); + } + return elm.css({ + position: "absolute", + bottom: padding_bottom, + top: "auto" + }).trigger("sticky_kit:bottom"); + } + } + }; + recalc_and_tick = function() { + recalc(); + return tick(); + }; + detach = function() { + detached = true; + win.off("touchmove", tick); + win.off("scroll", tick); + win.off("resize", recalc_and_tick); + $(document.body).off("sticky_kit:recalc", recalc_and_tick); + elm.off("sticky_kit:detach", detach); + elm.removeData("sticky_kit"); + elm.css({ + position: "", + bottom: "", + top: "", + width: "" + }); + parent.position("position", ""); + if (fixed) { + if (manual_spacer == null) { + if (el_float === "left" || el_float === "right") { + elm.insertAfter(spacer); + } + spacer.remove(); + } + return elm.removeClass(sticky_class); + } + }; + win.on("touchmove", tick); + win.on("scroll", tick); + win.on("resize", recalc_and_tick); + $(document.body).on("sticky_kit:recalc", recalc_and_tick); + elm.on("sticky_kit:detach", detach); + return setTimeout(tick, 0); + }; + for (i = 0, len = this.length; i < len; i++) { + elm = this[i]; + fn($(elm)); + } + return this; + }; + +}).call(this);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/mypandocfilters/graphviz-file.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +""" +Pandoc filter to process code blocks with class "graphviz" into +graphviz-generated images. + +Needs pygraphviz +""" + +import os +import sys + +import pygraphviz + +from pandocfilters import toJSONFilter, Para, Image, get_filename4code, get_caption, get_extension, get_value + +def graphviz(key, value, format, _): + if key == 'CodeBlock': + [[ident, classes, keyvals], file] = value + if "graphviz-file" in classes: + caption, typef, keyvals = get_caption(keyvals) + prog, keyvals = get_value(keyvals, u"prog", u"dot") + filetype = get_extension(format, "svg", html="svg", latex="pdf") + with open(file) as f: + code = f.read() + dest = get_filename4code("graphviz", code, filetype) + + if not os.path.isfile(dest): + g = pygraphviz.AGraph(string=code) + g.layout() + g.draw(dest, prog=prog) + sys.stderr.write('Created image ' + dest + '\n') + + return Para([Image([ident, ['graphviz'], keyvals], caption, [dest, typef])]) + +if __name__ == "__main__": + toJSONFilter(graphviz)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/mypandocfilters/raw-file.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,24 @@ +#!/usr/bin/env python +""" +Insert a raw-file as HTML code block +""" + +import panflute as pf + + +def action(elem, doc): + if isinstance(elem, pf.CodeBlock) and 'raw-file' in elem.classes: + filepath = elem.text + + with open(filepath, 'r') as fd: + content = fd.read() + + return pf.RawBlock('<pre>%s</pre>' % content, "html") + # elem.text = content + +def main(doc=None): + return pf.run_filter(action, doc=doc) + + +if __name__ == '__main__': + main()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/prepare.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,41 @@ +#!/bin/bash +set -euo pipefail + +# Prepare pandoc filters +if [ -d pandocfilters/.git ]; then + (cd pandocfilters && git remote update && git merge --ff-only) +else + git clone https://github.com/Lothiraldan/pandocfilters.git +fi + +pip2 install pandocfilters +pip2 install pygraphviz +pip2 install panflute +pip2 install hg+https://bitbucket.org/octobus/mercurial_docgraph +pip2 install hg-evolve + +mkdir -p graphs output + +CMD_NOT_FOUND=0 +check_command() { + cmd=$1 + if ! which "$cmd" >/dev/null 2>&1; then + echo "Error: command '$cmd' not found in \$PATH" + echo "Please install '$cmd'" + CMD_NOT_FOUND=1 + else + echo "$cmd command was found" + fi +} + +check_command pandoc +check_command aha + +if [ "$CMD_NOT_FOUND" -ne "0" ]; then + exit 1 +fi + +# Prepare directory for repositories generated by the training.t file +mkdir -p base-repos + +rm -Rf base-repos/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/scripts.js Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,157 @@ + +$(document).ready(function () { + /* uk-nav-parent-icon */ + $(".menu-begin ul:first-child").addClass('uk-nav uk-nav-side'); + $(".menu-begin ul:first-child").data('uk-nav', '{multiple:false}'); + $(".menu-begin ul:first-child").attr('data-uk-nav', '{multiple:false}'); + + // Parent click + $(".uk-parent > a").on('click', function (event) { + + event.preventDefault(); + $(".uk-parent > a").parent().removeClass('uk-active'); + $(this).parent().toggleClass('uk-active'); + + var hash = $(this).attr('href').split('#')[1]; + + // scroll.To(hash); + scrollTo(hash); + // $('body').scrollTo(hash); + // $('body').scrollTo(hash,{duration:'slow', offsetTop : '50'}); + $('a[href="' + hash + '"]').addClass('uk-active'); + }); + +}); + +function scrollTo(hash) { + + location.hash = "#" + hash; + +} + +function setStickyMenu () { + + var options = { + bottoming: false, + inner_scrolling: false + }; + + var sticky = ".uk-overflow-container"; + + + + + + + var width = $(window).width(); + + if (width >= 768) { + + $(".uk-nav > li").addClass('uk-parent'); + $(".menu-begin ul > li > ul").addClass('uk-nav-sub'); + + $('.uk-parent').removeClass('uk-open'); + $('.uk-parent div').addClass('uk-hidden'); + + $(sticky).stick_in_parent(options); + + } else { + + + $('.uk-parent').addClass('uk-open'); + + $('.uk-parent div').removeClass('uk-hidden'); + $('.uk-parent div').removeAttr('style'); + $('.uk-nav li').removeClass('uk-parent'); + + + $(sticky).trigger("sticky_kit:detach"); + } +}; + +$(document).ready(function(){ + + $(".pager").wrapInner( '<ul class="uk-pagination-left uk-pagination"></ul>' ); + $(".pager a").wrap( '<li></li>' ); + $(".pager b").wrap( '<li class="uk-active"></li>' ); + $(".pager b").wrapInner( '<span></span>' ); + $(".pager b span").unwrap( ); + + // Normalize tables without style + $( "table" ).addClass( "uk-table" ); + + // Normalize tables without style + $( "form" ).addClass( "uk-form" ); + + + +}); + +$(document).ready(function () { + setStickyMenu(); + $(window).on('resize', function () { + setStickyMenu(); + }); +}); + + +$(document).ready(function () { + $( 'table' ).addClass( "table" ); +}); + +/* +var scroll = (function() { + + var elementPosition = function(a) { + return function() { + return a.getBoundingClientRect().top; + }; + }; + + var scrolling = function( elementID ) { + + var el = document.getElementById( elementID ), + elPos = elementPosition( el ), + duration = 400, + increment = Math.round( Math.abs( elPos() )/40 ), + time = Math.round( duration/increment ), + prev = 0, + E; + + function scroller() { + E = elPos(); + + if (E === prev) { + return; + } else { + prev = E; + } + + increment = (E > -20 && E < 20) ? ((E > - 5 && E < 5) ? 1 : 5) : increment; + + if (E > 1 || E < -1) { + + if (E < 0) { + window.scrollBy( 0,-increment ); + } else { + window.scrollBy( 0,increment ); + } + + setTimeout(scroller, time); + + } else { + + el.scrollTo( 0,0 ); + + } + } + + scroller(); + }; + + return { + To: scrolling + } + +})(); +*/ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/slides.md Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,2447 @@ +--- +title: Changeset Evolution training +author: | + <span style="text-transform: none;"><small>Boris Feld<br/><a href="https://octobus.net">octobus.net</a></small></span> +--- + +# Introduction + +## Welcome + +Hello everyone, and welcome to this Changeset Evolution training. During this session, you will learn how to safely rewrite history with Mercurial and Evolve, and how to collaborate together with your colleagues while rewriting the history at the same time. + +This training is designed to last approximately ¾ hours. + +You will use this repository during the training: [https://bitbucket.org/octobus/evolve_training_repo](https://bitbucket.org/octobus/evolve_training_repo). Please clone it somewhere relevant. + +```bash +$ hg clone https://bitbucket.org/octobus/evolve_training_repo +$ cd evolve_training_repo +``` + +Copy the provided hgrc to ensure a smooth training experience: + +```bash +$ cp hgrc .hg/hgrc +``` + +This training support will contains commands you are expected to type and launch. These commands will be in the following format: + +``` +$ COMMAND YOU ARE EXPECTED TO TYPE +output you are expecting to see +``` + +## Preliminary checks + +#### Mercurial version + +First let's use the following command to verify which version of Mercurial you are using: + +``` +$ hg --version +Mercurial Distributed SCM (version 4.4.2) +(see https://mercurial-scm.org for more information) + +Copyright (C) 2005-2017 Matt Mackall and others +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +``` + +You need at least Mercurial version `4.1`. If you don't have a recent enough version, please call your instructor. + +In order to activate the Evolve extension, add these lines in your user configuration (using the command `hg config --edit`): + +```ini +[extensions] +evolve = +topic = +``` + +#### Mercurial extensions + +Now let's check the version of your extensions. You will need all of these for the training: + +``` +$ hg --version --verbose +[...] + evolve external 7.1.0 + topic external 0.6.0 + rebase internal + histedit internal +``` + +# The Basics + +<!-- #### What is Changeset Evolution? + +With core Mercurial, changesets are permanent and history rewriting has been discouraged for a long time. You can +commit new changesets to modify your source code, but you cannot +modify or remove old changesets. + +For years, Mercurial has included various commands that allow +history modification: ``rebase``, ``histedit``, ``commit --amend`` and so forth. +However, there's a catch: until now, Mercurial's various mechanisms for +modifying history have been *unsafe* and expensive, in that changesets were +destroyed (“stripped”) rather than simply hidden and still easy to recover. + +Changeset Evolution makes things better by changing the behaviour of most existing +history modification commands so they use a safer mechanism (*changeset +obsolescence*, covered below) rather than the older, less safe *strip* +operation. + +``evolve`` is built on infrastructure in core Mercurial: + + * *Phases* (starting in Mercurial 2.1) allow you to distinguish + mutable and immutable changesets. + + * *Changeset obsolescence* (starting in Mercurial 2.3) is how + Mercurial knows how history has been modified, specifically when + one changeset replaces another. In the obsolescence model, a + changeset is neither removed nor modified, but is instead marked + *obsolete* and typically replaced by a *successor*. Obsolete + changesets usually become *hidden* as well. Obsolescence is a + disabled feature in Mercurial until you start using ``evolve``. + + XXX More than just than obsolescence in core ? XXX + + XXX The part below is a bit overselling XXX + +Some of the things you can do with ``evolve`` are: + + * Fix a mistake immediately: “Oops! I just committed a changeset + with a syntax error—I'll fix that and amend the changeset so no + one sees my mistake.” (While this is possible using default + features of core Mercurial, Changeset Evolution makes it safer.) + + * Fix a mistake a little bit later: “Oops! I broke the tests three + commits back, but only noticed it now—I'll just update back to the + bad changeset, fix my mistake, amend the changeset, and evolve + history to update the affected changesets.” + + * Remove unwanted changes: “I hacked in some debug output two + commits back; everything is working now, so I'll just prune that + unwanted changeset and evolve history before pushing.” + + * Share mutable history with yourself: say you do most of your + programming work locally, but need to test on a big remote server + somewhere before you know everything is good. You can use + ``evolve`` to share mutable history between two computers, pushing + finely polished changesets to a public repository only after + testing on the test server. + + * Share mutable history for code review: you don't want to publish + unreviewed changesets, but you can't block every commit waiting + for code review. The solution is to share mutable history with + your reviewer, amending each changeset until it passes review. + + * Explore and audit the rewrite history of a changeset. Since Mercurial is + tracking the edits you make to a changeset, you can look at the history of + these edits. This is similar to Mercurial tracking the history of file + edits, but at the changeset level. --> + +In this section, we are going to learn how to do basic history rewriting like rewriting a changeset or rebasing. + +### Amend + +The smallest possible history rewriting is rewriting a changeset description message. We often save and close the editor too early, and/or haven't seen a typo. + +It is very easy to fix a changeset description message, so let's do that. First be sure that you are in your clone of the `evolve_training_repo`. then update to the `typo` branch: + +``` +$ hg update typo +``` + +Check what the current repository looks like: + +~~~raw-file +output/fix-a-bug-base.log +~~~ + +~~~graphviz-file +graphs/fix-bug-1.dot +~~~ + +We have a root commit and another based on it. Double-check that you are on the right changeset with the `hg summary` command: + +~~~raw-file +output/fix-a-bug-base-summary.log +~~~ + +The current commit description message seems wrong, `Fx bug`, there is definitely a letter missing. Let's fix this typo with the `hg commit` command. + +Usually, the `hg commit` is used to create new commit but we can use the ``--amend`` option to instead modify the current commit (see `hg help commit` for more information): + +~~~ +$ hg commit --amend --message "Fix bug" +~~~ + +Let's take a look at the repository now: + +~~~raw-file +output/amend-after.log +~~~ + +~~~graphviz-file +graphs/fix-bug-2.dot +~~~ + +The logs before and after amending looks pretty similar, we are going to analyze the differences later. Did you catch the differences? + +### Rebase + +<!-- XXX probably needs a sentence about the merge (Why do you want to avoid it) XXX --> + +Let's try to rebase something now. Let's say that you have a branch named `build/linuxsupport-v2` which was started on another branch named `build/v2`. Everything was fine until `build/v2` grew a new commit, and now you want to rebase `build/linuxsupport-v2` on top of `build/v2` to be up-to-date with other the changes: + +``` +$ hg update build/linuxsupport-v2 +``` + +~~~raw-file +output/rebase-before.log +~~~ + +~~~graphviz-file +graphs/rebase-before.dot +~~~ + +<!-- XXX-REVIEW: Explain rebase CLI interface --> + +Let's rebase our branch on top of `build/v2` with the `hg rebase` command. The `hg rebase` command have many ways to select commits: + +1. Explicitly select them using "--rev". +2. Use "--source" to select a root commit and include all of its descendants. +3. Use "--base" to select a commit; rebase will find ancestors and their descendants which are not also ancestors of the destination. +4. If you do not specify any of "--rev", "source", or "--base", rebase will use "--base ." as above. + +For this first example, we are gonna stays simple and explicitly select the commits we want to rebase with the `--rev` option. + +The `hg rebase` command also accepts a destination with the ``--dest`` option. And finally, as we are using named branches, don't forget to use the `--keepbranches` or the rebased commits will be on the wrong branch: + +~~~raw-file +output/rebase.log +~~~ + +Now we have a nice, clean and flat history: + +~~~raw-file +output/rebase-after.log +~~~ + +~~~graphviz-file +graphs/rebase-after.dot +~~~ + +For more details about how to use the `hg rebase` command, see `hg help rebase`. + +### Under the hood + +What did happened when we just ran the `hg amend` and `hg rebase` commands? What was done exactly to make the whole process work seamlessly? + +Let's go back to our previous amend example. + +##### Amend + +When we did our amend, the status of the repository was: + +~~~raw-file +output/behind-the-hood-amend-before-hash-hidden.log +~~~ + +~~~graphviz-file +graphs/fix-bug-1.dot +~~~ + +And after the amend, the repository looked like: + +~~~raw-file +output/behind-the-hood-amend-after.log +~~~ + +~~~graphviz-file +graphs/fix-bug-2.dot +~~~ + +Do you see what is the difference? + +The big difference, apart from the fixed changeset message, is the revision hash and revision number. The `Fix bug` revision changed from `d2eb2ac6a5bd` to `708369dc1bfe`. It means that the fixed changeset is a new one. But where did the old changeset go? + +It didn't actually go very far, as it just became **hidden**. When we rewrite a changeset with the Evolve extension, instead of blindly delete it, we create a new changeset and hide the old one, which is still there, and we can even see it with the `--hidden` option available on most Mercurial commands: + +~~~raw-file +output/under-the-hood-amend-after-log-hidden.log +~~~ + +Notice the `x` in the log output which shows that a changeset is hidden. + +In addition to hiding the original changeset, we are also storing additional information which is recording the relation between a changeset, the **precursor** and its **successor**. It basically stores the information that the commit **X** was rewritten into the commit **Y** by the user **U** at the date **D**. This piece of information is stored in something called an **obsolescence marker**. It will be displayed like this: + +~~~graphviz-file +graphs/fix-bug-3.dot +~~~ + +Here the commit **5d48a444aba7** was rewritten into **708369dc1bfe**. Also please notice the difference of style of the commit **5d48a444aba7**, that's because it have been rewritten. + +##### Rebase + +**Successors** don't need to share anything with their **precursor**. They could have a different description message, user, date or even parents. + +Let's look at our earlier rebase example. The status before the rebase was: + +~~~raw-file +output/behind-the-hood-rebase-before-hash-hidden.log +~~~ + +~~~graphviz-file +graphs/rebase-before.dot +~~~ + +And after it was: + +~~~raw-file +output/behind-the-hood-rebase-after.log +~~~ + +~~~graphviz-file +graphs/rebase-after.dot +~~~ + +Did the same thing happen under the hood? + +Yes, exactly! The old changesets are still around, and they are just hidden. + +~~~raw-file +output/rebase-after-hidden.log +~~~ + +And we created three **obsolescence markers**, between each rebased commit and its **successor**: + +~~~graphviz-file +graphs/rebase-after-hidden.dot +~~~ + +### Evolution History + +Mercurial is designed to track the history of files. Evolution goes beyond, and tracks the history of the history of files. It basically tracks the different versions of your commits. + +As it is a new dimension of history, the classical Mercurial commands are not always the best to visualize this new history. + +We have seen that we can see the **hidden** changesets with the `--hidden` option on `hg log`: + +~~~raw-file +output/under-the-hood-amend-after-log-hidden.log +~~~ + +To visualize the **obsolescence history** of a particular changeset, we can use the dedicated command `hg obslog`. The option are quite similar to `hg log` (you can read `hg help obslog` for more information): + +~~~raw-file +output/under-the-hood-amend-after-obslog.log +~~~ + +We can even print what changed between the two versions with the `--patch` option: + +~~~raw-file +output/under-the-hood-amend-after-obslog-patch.log +~~~ + +Obslog works both ways, as it can display **precursors** and **successors** with the `--all` option: + +```raw-file +output/under-the-hood-amend-after-obslog-no-all.log +``` + +~~~raw-file +output/under-the-hood-amend-after-obslog-all.log +~~~ + +~~~graphviz-file +graphs/fix-bug-3.dot +~~~ + +We can also use obslog on the changesets that we rebased earlier: + +~~~raw-file +output/under-the-hood-rebase-after-obslog.log +~~~ + +Why the `hg obslog` command is only showing two commits while we rebased three of them? + +```raw-file +output/under-the-hood-rebase-after-obslog-branch.log +``` + +And why the `hg obslog` command show disconnected graphs when asking for the obslog of the whole branch? + +~~~graphviz-file +graphs/rebase-after-hidden.dot +~~~ + +While these two obsolescence logs look very similar —because they show a similar change—, the two changesets log histories looked quite different. + +Using the `hg log` command to understand the Evolution history is hard because it is designed for displaying the files history, not the Evolution history. The `hg obslog` has been specially designed for this use-case and is more suited for this use-case. + +#### TortoiseHG + +TortoiseHG should be able to display obsolescence history for your repositories. + +To display all the **hidden** commits, we need to click on the **search icon**, then on the **Show/Hide hidden changesets** at the right of the **filter** check box. It is also possible to provide a *revset* to filter the repository, for example `:6 + ::20` to display only the revisions we have been working with until now: + +![](img/thg-obs.png) + +<!-- #### Deroulement + +Travail chacun de son côté pour apprendre à utiliser: + +- Réecriture de changeset +- Affichage de l'obsolescence, log, obslog + + +- Vérifier que chacun sait utiliser les commandes de base +- Vérifier que chacun sait utiliser les commandes de visu, hg log, hg log -G, thg? +=> Pas trop longtemps // répartir + +- Créer un commit +- Le amend sans evolve == bundle +- Strip? +- rebase sans evolve? +- Why is it bad? exemple +(Peut-etre pas leur faire pratiquer amend sans evolve, ca prends du temps) + +- With evolve, now +- Activate it, check version +- Amend with evolve +- rebase with evolve + +- What happened? +- View obs-history, hg log, obslog --> + + +# Medium level + +## More rewriting commands + +The `hg amend` and `hg rebase` commands are the foundations for changeset evolution in Mercurial. You could do everything with these, but, luckily for us, the evolve extension provides human-friendly commands for common needs. We are going to see them now: + +### Amend + +The Evolve extension provides its own `hg amend` command, which is similar to the `hg commit --amend` that we used previously, and adds several nice features: + +- The `-e`/`--edit` option edits the commit message in an editor, which is not opened by default any more. +- The user and date can be updated to the current ones with the `-U`/`--current-user` and `-D`/`--current-date` options. +- More capabilities for rewriting the changeset. + +The `hg amend` command accepts either file paths, to add all the modifications on these files in the current changeset, or the `-i`/`--interactive` option to select precisely what to add in it. + +We are going to use it to rewrite the author of the changeset: + +``` +$ hg update amend-extract +``` + +We have two commits on the **amend-extract** branch: + +```raw-file +output/amend-extract-before.log +``` + +The user for the **amend-extract** head seems wrong, so let's fix it with the `hg amend` command: + +```raw-file +output/amend-user.log +``` + +Now let's check that the user has been amended correctly: + +```raw-file +output/amend-user-after-export.log +``` + +The user is the good one, but the diff looks weird. It seems that both a bad file **and** an incorrect line have slipped in this commit. We need to fix that. + +There are several solutions here, and we could manually edit the file and amend it. But, luckily for us, the `hg amend` command also has a very helpful option named `--extract` that will help us. + +### Amend extract + +The `hg amend` command is meant to move file modifications from your working directory to the current changeset (which is considered as the parent of working directory). `hg amend` also provides the option `--extract` that can be used to invert the meaning of the command: with this option, `hg amend` will move the file modifications from your current changeset to your working directory. + +This is often used to remove a file or a line that is not meant to be in the current commit. + +As usual, we can either pass file paths or use the `-i` option to select which lines to extract. + +First, let's extract the badfile: + +```raw-file +output/amend-extract-badfile.log +``` + +Now let's check the status of the changeset and the working directory: + +```raw-file +output/amend-extract-badfile-after-export.log +``` + +The file is not included in the commit anymore! Did it just vanish? What if you wanted to keep it and, for example, put it in another commit? + +Don't worry, the extracted files and lines still are in your working directory: + +```raw-file +output/amend-extract-badfile-after-status.log +``` + +As we are not going to need this file anymore, let's forget it with the `hg revert` command: + +```raw-file +output/amend-extract-badfile-after-revert.log +``` + +Also don't forget to remove the file: + +```bash +$ rm badfile +``` + +Ok. Now we still have a line to extract from our commit, so let's use the handy interactive mode of `hg amend --extract` to extract lines: + +```raw-file +output/amend-extract.log +``` + +Much better! One last thing, as the line that we extracted is still in our working directory, just like when we extracted a file: + +```raw-file +output/amend-extract-after-status.log +``` + +```raw-file +output/amend-extract-after-diff.log +``` + +Don't forget to revert the change, as we are not going to need it any more: + +```raw-file +output/amend-extract-after-revert.log +``` + +Now let's take a look at the obsolescence history: + +```raw-file +output/amend-extract-after-obslog.log +``` + +The obslog is read from bottom to top: + +- First we rewrite the user, +- Then we extracted a whole file, +- Then we extracted a line from a file + +We have made three changes that generated three **successors**. + +```graphviz-file +graphs/amend-extract-after-hidden.dot +``` + +### Fold + +Sometimes we want to group together several consecutive changesets. Evolve has a command for that: `hg fold`. First, let's update to the right branch: + +``` +$ hg update fold +``` + +Three changesets change the same file, and they could be folded together. This would make a cleaner and more linear history, and hide those pesky intermediate changesets: + +```raw-file +output/fold-before.log +``` + +```graphviz-file +graphs/fold-before.dot +``` + +We all have been in a similar situation. Let's make a nice and clean changeset with fold: + +```raw-file +output/fold.log +``` + +That was easy! + +```raw-file +output/fold-after.log +``` + +```raw-file +output/fold-after-hidden.log +``` + +Can you imagine what the graphs will looks like? + +```raw-file +output/fold-after-hidden-obslog.log +``` + +```graphviz-file +graphs/fold-after-hidden.log +``` + +### Split + +Sometimes you want to `fold` changesets together, and sometimes you want to `split` a changeset into several ones, because it is too big. + +``` +$ hg update split +``` + +Evolve also has a command for that, `hg split`: + +```raw-file +output/split-before.log +``` + +```graphviz-file +graphs/split-before.dot +``` + +Split accepts a list of revisions and will interactively ask you how you want to split them: + +```raw-file +output/split.log +``` + +Now let's check the state of the repository: + +```raw-file +output/split-before-after.log +``` + +```graphviz-file +graphs/split-before-after-hidden.dot +``` + +It looks good. What about the obsolescence history? + +```raw-file +output/split-after-obslog.log +``` + +```raw-file +output/split-after-obslog-all.log +``` + +### Prune + +After rewriting and rebasing changesets, the next common use case for history rewriting is removing a changeset. + +But we can't permanently remove a changeset without leaving a trace. What if other users are working with the changeset that we want to remove? + +The common solution is to mark the changeset as removed, and simulate the fact that it has been removed. + +This is why the Evolve extension is offering the `prune` command. Let's try to prune a changeset: + +``` +$ hg update prune +``` + +```raw-file +output/prune-before.log +``` + +```graphviz-file +graphs/prune-before.dot +``` + +`prune` is easy to use, just give it the revisions you want to prune: + +```raw-file +output/prune.log +``` + +Now the changeset is not visible any more: + +```raw-file +output/prune-after.log +``` + +But we can still access it with the `--hidden` option: + +```raw-file +output/prune-after-hidden.log +``` + +The output of `obslog` changes a bit when displaying pruned changesets: + +```raw-file +output/prune-after-obslog.log +``` + +```graphviz-file +graphs/prune-after-hidden.dot +``` + +### Histedit + +The `hg histedit` command is a power-user command. It allows you to edit a linear series of changesets, and applies a combination of operations on them: + +- 'pick' to [re]order a changeset +- 'drop' to omit changeset +- 'mess' to reword the changeset commit message +- 'fold' to combine it with the preceding changeset (using the later date) +- 'roll' like fold, but discarding this commit's description and date +- 'edit' to edit this changeset (preserving date) +- 'base' to checkout changeset and apply further changesets from there + +It's similar to the `git rebase -i` command. + +First, let's update to the right branch: + +``` +$ hg update histedit +``` + +```raw-file +output/histedit-before-log.log +``` + +```graphviz-file +graphs/histedit-before.dot +``` + +When launching the `hg histedit` command, an editor will show up with the following contents: + +```raw-file +output/histedit-no-edit.log +``` + +Swap the first two lines with your text editor: + +```raw-file +output/histedit-commands.log +``` + +Save and exit. Histedit will apply your instructions and finish. + +Let's see the state of the repository: + +```raw-file +output/histedit-after-log.log +``` + +```raw-file +output/histedit-after-log-hidden.log +``` + +```graphviz-file +graphs/histedit-after-hidden.dot +``` + +<!-- #### Deroulement + +- prune with evolve + +- advanced commands +- fold +- split --> + +## Stack + +### Stack definition + +One big problem when working with a DVCS to identify and switch between the different features/bugfixes you are working on. + +### Named branches + +One solution is to use **named branches**. Named branches are a battle-tested, long-supported solution in Mercurial. Basically, a branch name is stored inside each changeset. + +This solution has several advantages: + +- It's supported in all recent-ish Mercurial versions. +- It's simple to use. +- Most tools are supporting it. + +But it also has several disadvantages: + +- Branches do not disappear once they are merged. You need to explicitely close them with `hg commit --close-branch`. +- Branches are lost when rebasing them without the `--keepbranches` option of the `hg rebase` command. +- New branches needs to be explicitly pushed with the `--new-branch` option of the `hg push` command. + +We will use named branches for this training, but other solutions are possible, like [topics](https://www.mercurial-scm.org/doc/evolution/tutorials/topic-tutorial.html). + +<!-- #### Topics + --> + +### Stack + +The `topic` extension provides a command to show your current stack, no matter how you defined it. Let's try it on some changesets that we rewrote earlier: + +``` +$ hg update typo +``` + +```raw-file +output/stack-typo.log +``` + +The stack output shows three important data: + +- First, which branch you are working on (a.k.a. the **current** branch). +- Then, all the commits that you are currently working on, with the current one highlighted. +- Finally, which commit your branch is based on (**b0**). + +This branch is not very interesting, so let's move to another one. + +``` +$ hg update build/linuxsupport-v2 +``` + +```raw-file +output/stack-rebase.log +``` + +This is more interesting, as now we can see all the three changesets grouped together in the same view. The stack view provides a nice and linear view, even if the changesets are not immediate neighbors. + +### Stack movement + +There is an easy way to navigate in your stack, the `hg next` and `hg prev` commands: + +```raw-file +output/stack-rebase-prev-from-b3.log +``` + +```raw-file +output/stack-rebase-stack-b2.log +``` + +And now for the `hg next` command: + +```raw-file +output/stack-rebase-next-from-b2.log +``` + +```raw-file +output/stack-rebase.log +``` + +The stack view also displays nice and easy relative ids for these changesets. You can use theses ids in all commands, for example with the `hg export` command: + +```raw-file +output/stack-rebase-export-b1.log +``` + +Or with the `hg update` command: + +```raw-file +output/stack-rebase-update-b2.log +``` + +These ids are handy because you don't need to manipulate changeset ids or revision numbers: contrary to the latters, the formers won't be affected by history edition. They only depend on their order in the branch. + +```raw-file +output/stack-rebase-stack-b2.log +``` + +### Edit mid-stack + +Now that we are in the middle of a stack, let's try amending a commit. The current commit message ends with a dot `.`, and we want to remove it: + +```raw-file +output/stack-rebase-stack-b2.log +``` + +```raw-file +output/edit-mid-stack.log +``` + +The message `1 new orphan changesets` means that, by amending a changeset having a child, this child is now **unstable**, as we can see with the `hg stack` command: + +```raw-file +output/edit-mid-stack-after-stack.log +``` + +`hg stack` tries to simplify the view for you. We have amended **b2**, and **b3**'s parent is the precursor version of **b2**, so it is not stable any more. It is now **orphan**. + +For once, let's use log to see in detail in which situation we are: + +```raw-file +output/edit-mid-stack-after-log.log +``` + +```graphviz-file +graphs/edit-mid-stack-after.dot +``` + +How can we resolve this situation? It is actually very easy, and we are going to see how in the next section. + +<!-- #### Deroulement + +Tout seul: + +- Topic? stack? + +- Comment définir ce sur quoi on travaille? + +- Solution possible: named branches +- Avantages des branches nommées +- Inconvénients des branches nommées + +- Solution possible: topic +- Avantages des topic +- Inconvénients des topic +- Commands: hg stack, hg topics, hg topics --age, hg topics --verbose +(Pas forcément topic, risque de confusion) + +- Visualiser une stack avec hg stack, hg show stack? +- Se déplacer dans une stack avec hg prev/hg next + +- Editer au milieu d'une stac + +- Absorb? (Pas sous windows dur à installer) --> + +## Basic instabilities + stabilization + +Instabilities are a normal step when using Evolve-powered workflows. Several tools are provided to fix them smoothly. + +#### Log + +First, let's clarify some vocabulary. An **obsolete** changeset is a changeset that has been rewritten. In the current stack, only one commit is `obsolete`: + +```raw-file +output/basic-stabilize-before-log-obsolete.log +``` + +A changeset can also be **unstable**, meaning that it could be subject to one or more **instabilities**: + +* **orphan**, a changeset whose an ancestor is **obsolete**. +* **content-divergent**, a changeset which has been rewritten in two different versions. +* **phase-divergent**, a changeset which has been both rewritten and published. + +For the moment, we will only see the **orphan** instability. We can display the **instabilities** of a commit with the `{instabilities}` template keyword: + +```raw-file +output/basic-stabilize-before-log-instabilities.log +``` + +Here we have also one **orphan** commit, which is the child of the **obsolete** commit. + +#### Evolve --list + +The `hg evolve` command has a `--list` option which can list all the instabilities of your repository. + +```raw-file +output/basic-stabilize-before-evolve-list.log +``` + +#### TortoiseHG + +Tortoise HG also has a nice support for displaying the instabilities of your repository: + +![](img/thg-mid-stack.png) + +If you want to filter to get a better view, you can use the *revset* `branch(build/linuxsupport-v2)`: + +![](img/thg-mid-stack-filter.png) + +#### Stabilization using `hg next --evolve` + +```raw-file +output/edit-mid-stack-after-stack.log +``` + +In our current situation, a simple solution to solve the instability is to use the `hg next` command with the `--evolve` option. It will update to the next changeset on the stack, and stabilize it if necessary: + +```raw-file +output/basic-stabilize-next-evolve.log +``` + +Here, it just rebased our old version of `b3` on top of the new version of `b2`. + +And now `hg stack` shows us a clean view again: + +```raw-file +output/basic-stabilize-after-stack.log +``` + +That's better! + +```graphviz-file +graphs/basic-stabilize-after-stack.dot +``` + +<!-- #### hg evolve + +XXX-REVIEW: Later --> + +# Advanced + +## Moving change from one commit to another + +Create two commits: + +- The first one create a new file, add some content in it. +- The second one create another file and modify the first file. + +Now try to move the change on the first file present in the second commit back in the first commit so that the first commit contains all change on the first file and the second change contains all changes on the second file. + +## Exchange + +Coming Soon™ + +<!-- ## Exchange --> + +<!-- #### Obsolescence History Synchronization + +XXX Too theoritical (except first sentence maybe) XXX + +While obsolescence markers are already useful locally, they unlock their true power when they are exchanged. They are the piece of information that are fundamental to achieve the goal of synchronizing repositories state. + +If two people starts with the same repository and they each make some modifications, once exchanging all their obsolescence marker with their partner; they should have the same repository state. + +Given a repository state R, if user A creates obs-markers OBSA and user B creates obs-markers OBSB, `R + OBSA + OBSB = R + OBSB + OBSA`. + +This characteristic is the foundation to make people confident with their modification as they know that they will be able to synchronize with someone and have exactly the same state. XXX-REVIEW BOF + +#### When are exchanged obsolescence markers + +Obsolescence markers are exchanges during all usual exchange methods: + +- Obsolescence markers related to pushed heads are pushed during `hg push`. +- Obsolescence markers related to pulled heads are also pulled during `hg pull`. +- Obsolescence markers are included in bundles. + +New obsolescence markers are automatically applied, so after a `pull` some changesets could become obsolete as they have been rewritten by a new changeset you just pulled. + +XXX-REVIEW: Add example? + +The obsolescence markers only apply to draft changesets though. + +###### Let's exchange obsmarkers + +Let's try to push and pull some obsolescence-markers, first copy your repository somewhere else, for example: + +```raw-file +output/basic-exchange-clone.log +``` + +#### Phases + +XXX Too theoritical XXX + +There is a dimension that have been overlooked until now. **Phases**. What are phases? Phases is an information about a changeset status, a changeset could be in one phase at any time: + +* **draft**, the default phase a changeset is just after committing it. This phase denotes that the changeset is still a work in progress. It could be rewritten, rebased, splitted, folded or even pruned before it's considered finished. This state allow a changeset to evolve into another version. +* **public**, the phase a changeset is when it's considered finished. The changeset would likely have been reviewed, tested and even released when they are in this state. This state forbids any rewriting on changeset which are public. +* **secret**, this phase is for changesets that should never be shared. It could be local-only modifications for your environment or a way to commit credentials without sharing it outside. This state allow a changeset to be rewritten, like to be rebased on the most up-to-date head for example. + +Phase are about changesets but they are not part of the commit information, meaning that changing the phase of a changeset does not change it's changeset hash. + +These phases are ordered (public < draft < secret) and no changeset can be in +a lower phase than its ancestors. For instance, if a changeset is public, all +its ancestors are also public. Lastly, changeset phases should only be changed +towards the public phase. + +Changeset are created in the **draft** phase by default and move to the **public** phase in several scenarios. + +#### Phase movement + +The original scenario for **phases** is to permits local rewriting of changesets that have not been pushed. You create draft changesets, you test them locally, possibly amend them, rebased them or clean it then you push it to a server and they become **public** at this occasion. + +While this scenario is pretty sensible, not altering shared commit make a lot of problems disappears, move powerful workflows could be unlocked when decoupling the sharing part with the publishing part. + +By default, hg server are in **publishing** mode, meaning that: + +- all draft changesets that are pulled or cloned appear in phase public on the client. + +- all draft changesets that are pushed appear as public on both client and server. + +- secret changesets are neither pushed, pulled, or cloned. + +Hg servers could also be configured into **non-publishing** mode with this configuration: + +```ini +[phases] +publish = False +``` + +When pushing to a **non-publishing** mode, draft changesets are not longer made **public** anymore, allowing people and teams to share unfinished works. This way, it's still possible to edit a changeset after sharing it, meaning that: + +- a changeset could be updated after it has been reviewed. +- a changeset could be updated after a Continuous Integration tool show that some tests on some platforms are broken. +- a changeset could be updated after a co-worker tried implementing another feature on top of it. + +#### Usual phase workflow + +While sharing unfinished works is powerful, move **draft** changeset to the **public** phase when pushing them to **publishing** server is powerful by its simplicity. Its easy to understand as **non-publishing** servers could be seen as work-in-progress while **publishing** servers is meant for public, finished work that you commit to never alter. XXX-REVIEW Bof + +The usual way of having both advantages is to have both a **non-publishing** server where developers push for sharing work and asking for review and another **non-publishing** server when ready changesets are pushed, marking them as **public**. + +This way the **publishing** repository will only contains **public** changesets while the **non-publishing** one will contains all the **public** changesets plus all the **drafts** changesets. + +#### Phase visualization + +Phase is not shown by default in `hg log`, but we can ask for it with the `{phase}` template: + +```raw-file +output/split-after-log-phase.log +``` + +It's also possible to use `hg phase` to recover the phase of a revision(s): + +```raw-file +output/split-after-phase.log +``` + +You might wondered why you saw different forms in the graphs before, that was the phase that were shown. From now on, public changesets will be shown as circles, drafts changesets will be shown as hexagons and secrets changesets will be shown as squares: + +```graphviz-file +graphs/phases.dot +``` + +#### Phase selection + +Phase have a few revsets for selecting changesets by their phases: + +- `public()`, select all public changesets. +- `draft()`, select all draft changesets. +- `secrets()`, select all secret changesets. + +It could be used to: + +- select all non-public changesets with `hg log -r "not public()"`. +- change all secret changesets to draft with `hg phase --draft "secret()"`. --> + +<!-- #### Deroulement + +Toujours tout seul: + +- push / pull +- phases --> + +<!-- ## Advanced --> + +<!-- #### Deroulement + +Advances use-cases: + +- Move part of a changeset to another (split+fold) --> + +<!-- ## Let's start the fun --> + +<!-- #### Deroulement + +À deux: + +- troubles, divergence, orphan +- troubles visualization +- troubles resolution +- collaboration workflow + +Parler du happy path d'abord --> + +<!-- ## Content to integrate (presentation old content) + +#### Once upon a time + +#### You fix a bug + +(With a small typo) + +~~~graphviz-file +graphs/fix-bug-1.dot +~~~ + +#### You write more code + +<img src="https://media0.giphy.com/media/13GIgrGdslD9oQ/giphy.gif"> + +#### Urgent merge + +<img src="https://media.giphy.com/media/OBnwDJW77acLK/giphy.gif"> + +#### Fix the fix + +But it's easy to fix them: + +~~~ {.sh} +hg commit --amend -m "Fix bug" +~~~ + +~~~graphviz-file +graphs/fix-bug-2.dot +~~~ + +#### Too fast! + +But wait you had local changes! And they get incorporated into the amend. + +<img src="https://media1.giphy.com/media/vMiCDfoKdJP0c/giphy.gif"> + +10 more minutes to unbundle revert the files, relaunch the tests, etc... + +#### With evolve now + +~~~graphviz-file +graphs/fix-bug-1.dot +~~~ + +#### Same CLI + +With evolve this time: + +~~~ {.sh} +hg commit --amend -m "Fix bug" +~~~ + +~~~graphviz-file +graphs/fix-bug-2.dot +~~~ + +#### Ok what the difference? + +#### Before / After + + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +Before: + +</div> + +<div class='right' style='order:2; width: 50%'> +After: + +~~~raw-file +output/fix-a-bug-with-evolve-1.log +~~~ + +</div> +</div> + +#### Difference is hidden + + +~~~raw-file +output/fix-a-bug-with-evolve-2.log +~~~ + +The old revision is still there! + +#### Impact + +* Easier to access obsolete changesets + - No more `.hg/strip-backup/` expedition +* Respect the append only model of Mercurial + - No large data movement on edition + - No cache trauma + +#### One more thing + +<img src="https://media.giphy.com/media/F3MoHzSjjJ16w/giphy.gif"> + +#### Track evolution + +~~~graphviz-file +graphs/fix-bug-3.dot +~~~ +~~~graphviz + digraph G { + rankdir="BT"; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + // Revisions + node[group=main]; + Parent -> "Fix bug"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Parent -> "Fx bug"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "Fx bug" -> "Fix bug"; + } +~~~ + +#### Obsmarker + +Stores relation between evolutions + + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF"]; + + node[group=obsolete, style="dotted, filled" fillcolor="#DFDFFF"]; + edge[dir=back, style=dotted, arrowtail=dot]; + "Predecessor" -> "Successor"; + + "Successor" [style="filled", fillcolor="#7F7FFF"]; + } +~~~ +</div> + +<div class='right' style='order:2; width: 50%'> + +* And some metas: + * User + * Date + * And others... +</div> +</div> + +## Topic + +#### Topic + +<pre> +$> hg topic myfeature +$> hg topics +<span style="color:green;"> * </span><span style="color:green;">myfeature</span> +</pre> + +#### Topic + +Topic branches are lightweight branches which disappear when changes are +finalized (move to the public phase). They can help users to organise and share +their unfinished work. + +#### Topic storage + +Like named-branches, topics are stored on the changeset. + +#### Head definition + +<pre> +$> hg log -G +@ <span style="color:olive;">changeset: 2:03a68957ddd8</span> +| tag: tip +| parent: 0:478309adfd3c +| user: Boris Feld <boris.feld@octobus.net> +| date: Mon Jul 24 22:39:27 2017 +0200 +| summary: default +| +| o <span style="color:olive;">changeset: 1:3d2362d21bb4</span> +|/ <span style="background-color:green;">topic: myfeature</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Mon Jul 24 22:39:55 2017 +0200 +| summary: myfeature +| +o <span style="color:olive;">changeset: 0:478309adfd3c</span> + user: Boris Feld <boris.feld@octobus.net> + date: Mon Jul 24 16:01:32 2017 +0200 + summary: ROOT +</pre> + +#### Heads + +<pre> +$> hg log -r 'head() and branch(default)' +<span style="color:olive;">changeset: 2:03a68957ddd8</span> +tag: tip +parent: 0:478309adfd3c +user: Boris Feld <boris.feld@octobus.net> +date: Mon Jul 24 22:39:27 2017 +0200 +summary: default +</pre> + +#### Name definition + +We can update to a topic directly: + +<pre> +$> hg update myfeature +switching to topic myfeature +1 files updated, 0 files merged, 2 files removed, 0 files unresolved +</pre> + +#### Pre-rebase + +<pre> +$> hg log -G +o <span style="color:olive;">changeset: 2:03a68957ddd8</span> +| tag: tip +| parent: 0:478309adfd3c +| user: Boris Feld <boris.feld@octobus.net> +| date: Mon Jul 24 22:39:27 2017 +0200 +| summary: default +| +| @ <span style="color:olive;">changeset: 1:3d2362d21bb4</span> +|/ <span style="background-color:green;">topic: myfeature</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Mon Jul 24 22:39:55 2017 +0200 +| summary: myfeature +| +o <span style="color:olive;">changeset: 0:478309adfd3c</span> + user: Boris Feld <boris.feld@octobus.net> + date: Mon Jul 24 16:01:32 2017 +0200 + summary: ROOT +</pre> + +#### Topic rebase + +Topics can be rebased easily on their base branch + +<pre> +$> hg rebase +rebasing 1:3d2362d21bb4 "myfeature" +switching to topic myfeature +</pre> + +#### Result + +<pre> +$> hg log -G +@ <span style="color:olive;">changeset: 3:0a51e0d4d460</span> +| tag: tip +| <span style="background-color:green;">topic: myfeature</span> +| user: Boris Feld <boris.feld@octobus.net> +| date: Mon Jul 24 22:39:55 2017 +0200 +| summary: myfeature +| +o <span style="color:olive;">changeset: 2:03a68957ddd8</span> +| parent: 0:478309adfd3c +| user: Boris Feld <boris.feld@octobus.net> +| date: Mon Jul 24 22:39:27 2017 +0200 +| summary: default +| +o <span style="color:olive;">changeset: 0:478309adfd3c</span> + user: Boris Feld <boris.feld@octobus.net> + date: Mon Jul 24 16:01:32 2017 +0200 + summary: ROOT +</pre> + +#### Topic push + +You can push topic without -f if you push only 1 head: + +<pre> +hg push -r myfeature +</pre> + +Even if the topic is not up-to-date to its branch. + +## Stack Workflow + +#### Stack + +<pre> +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:teal;">t4</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3 +<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2 +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Why Stack? + +* Feature = multiple steps, + +* Smaller = Simpler + +* Simpler = Earlier merge in trunk + +* Ease experiment with Alternative + +* etc… + +#### Prev + +<pre> +$> hg prev +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +[<span style="color:blue;">7</span>] Step3 +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:olive;">t4</span><span style="color:green;">:</span> Step4 +<span style="color:teal;">t3</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step3</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2 +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Next + +<pre> +$> hg next +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +[<span style="color:blue;">8</span>] Step4 +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:teal;">t4</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3 +<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2 +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### T\# + +<pre> +$> hg update --rev t2 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +[<span style="color:blue;">8</span>] Step4 +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:olive;">t4</span><span style="color:green;">:</span> Step4 +<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3 +<span style="color:teal;">t2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step2</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Editing mid-stack + +<pre> +$> hg update --rev t1 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +$> hg commit --amend -m "Step1" +<span style="color:gold;">3 new unstable changesets</span> +</pre> + +#### What have we done? + +<pre> +$> hg log -G -T compact +@ <span style="color:olive;">9</span>[tip] 1aa1be5ada40 Step1 +| +| o <span style="color:olive;">8</span> cf90b2de7e65 Step4 <span style="color:red;">(unstable)</span> +| | +| o <span style="color:olive;">7</span> e208d4205c8e Step3 <span style="color:red;">(unstable)</span> +| | +| o <span style="color:olive;">6</span> 673ff300cf3a Step2 <span style="color:red;">(unstable)</span> +| | +| <span style="color:grey;">x 5 8bb88a31dd28 Step</span> +|/ +o <span style="color:olive;">4</span> 3294c1730df7 Trunk +~ +</pre> + +#### Stack to the rescue! + +<pre> +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (unstable)</span> +<span style="color:olive;">t3</span><span style="color:red;">$</span> Step3<span style="color:red;"> (unstable)</span> +<span style="color:olive;">t2</span><span style="color:red;">$</span> Step2<span style="color:red;"> (unstable)</span> +<span style="color:teal;">t1</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step1</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Don't panic + +<pre> +$> hg next --evolve +move:[<span style="color:blue;">6</span>] Step2 +atop:[<span style="color:blue;">9</span>] Step1 +working directory now at <span style="color:olive;">d72473cbf9a6</span> +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (unstable)</span> +<span style="color:olive;">t3</span><span style="color:red;">$</span> Step3<span style="color:red;"> (unstable)</span> +<span style="color:teal;">t2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step2</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1 +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Go on + +<img src="https://media.giphy.com/media/KBx7fQoLxuV7G/giphy.gif"> + +#### Go on + +<pre> +$> hg next --evolve +move:[<span style="color:blue;">7</span>] Step3 +atop:[<span style="color:blue;">10</span>] Step2 +working directory now at <span style="color:olive;">4062d6ecd214</span> +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:olive;">t4</span><span style="color:red;">$</span> Step4<span style="color:red;"> (unstable)</span> +<span style="color:teal;">t3</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step3</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2 +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1 +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Go on + +<pre> +$> hg next --evolve +move:[<span style="color:blue;">8</span>] Step4 +atop:[<span style="color:blue;">11</span>] Step3 +working directory now at <span style="color:olive;">4dcd9dfedf1b</span> +$> hg stack +###### topic: <span style="color:green;">myfeature</span> +###### branch: feature +<span style="color:teal;">t4</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3 +<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2 +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1 +<span style="color:grey;">t0^ Trunk</span> +</pre> + +#### Go on + +<pre> +$> hg next --evolve +no children +</pre> + +#### Better! + +<pre> +$> hg log -G -T compact +@ <span style="color:olive;">12</span>[tip] 4dcd9dfedf1b Step4 +| +o <span style="color:olive;">11</span> 4062d6ecd214 Step3 +| +o <span style="color:olive;">10</span> d72473cbf9a6 Step2 +| +o <span style="color:olive;">9</span> 1aa1be5ada40 Step1 +| +o <span style="color:olive;">4</span> 3294c1730df7 Trunk +~ +</pre> + +#### More Rewrite Tools + +<table> +<tr> +<th>Operation</th> +<th>command</th> +</tr> +<tr> +<td>Modify</td> +<td>`hg amend`<br></td> +</tr> +<tr> +<td>Remove</td> +<td>`hg prune`<br></td> +</tr> +<tr> +<td>Move</td> +<td>`hg grab`<br></td> +</tr> +<tr> +<td>Split</td> +<td>`hg split`<br></td> +</tr> +<tr> +<td>Fold</td> +<td>`hg fold`<br></td> +</tr> +</table> + +#### Multi headed stack + +<pre> +$> hg log -G -T compact +@ <span style="color:olive;">6</span>[tip] 189f54192937 Step4.5 +| +| o <span style="color:olive;">5</span> c1a91e7c74f5 Step5 +|/ +o <span style="color:olive;">4</span> 826d2fbb601a Step4 +| +o <span style="color:olive;">3</span> 08bcdd8d972b Step3 +| +o <span style="color:olive;">2</span> 06cb53532f1b Step2 +| +o <span style="color:olive;">1</span> 3eb38d10980d Step1 +~ + +</pre> + +#### Multi headed stack + +<pre> +$> hg stack +###### topic: <span style="color:green;">myfeature</span> (<span style="color:olive;">2 heads</span>) +###### branch: feature +<span style="color:teal;">t6</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Step4.5</span><span style="color:teal;font-weight:bold;"> (current)</span> +<span style="color:grey;">t4^ Step4 (base)</span> +<span style="color:olive;">t5</span><span style="color:green;">:</span> Step5 +<span style="color:olive;">t4</span><span style="color:green;">:</span> Step4 +<span style="color:olive;">t3</span><span style="color:green;">:</span> Step3 +<span style="color:olive;">t2</span><span style="color:green;">:</span> Step2 +<span style="color:olive;">t1</span><span style="color:green;">:</span> Step1 +<span style="color:grey;">t0^ Trunk</span> +</pre> + +## Distributed Workflow + +#### propagation + +Obsolescence can be exchanged: + +* push, pull +* bundle / unbundle (hg 4.3+) + +(affects draft history only) + +#### Exchanging draft + + * Works on multiple machines + + * Collaborate with others + + * Whole new play field == new traps + +#### Example + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A"; + Root [shape="circle"]; + } +~~~ +</div> + +<div class='right' style='order:2; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A"; + Root [shape="circle"]; + } +~~~ +</div> +</div> + +#### time pass + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A1"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A1"; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class='right' style='order:2; width: 50%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A" -> B; + + Root [shape="circle"]; + } +~~~ +</div> +</div> + +#### Instability + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A1"; + "B"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A" -> "B"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A1"; + + Root [shape="circle"]; + B [fillcolor="#FF3535"]; + } +~~~ + +#### It's smart + +<img src="https://media2.giphy.com/media/ZThQqlxY5BXMc/giphy.gif"> + +#### Stabilization + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A1" -> "B1"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A" -> "B"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A1"; + "B" -> "B1"; + + Root [shape="circle"]; + } +~~~ + +#### rewrite anything? + +Phases enforce a reliable history: + +* **draft**: can we rewritten +* **public**: immutable part of the history + +Contact your local workflow manager. + +## Helpfull Tooling + +#### Summary + +<pre> +$> hg summary +<span style="color:olive;">parent: 10:890ac95deb83 </span>tip (unstable) + Head +branch: feature +commit: (clean) +update: (current) +phases: 9 draft +unstable: <span style="color:red;">1 changesets</span> +topic: <span style="color:green;">myfeature</span> +</pre> + +#### Topics + +<pre> +$> hg topics + 4.3compat + doc + evolvecolor + import-checker + more-output + obscache + obsfatefixes + obsmarkerbitfield + obsrangecacheiterative + packaging + prev-next + split + stack_unstable_bug + tutorial + * tutorialtypos +</pre> + +#### Topics age + +<pre> +$> hg topics --age + tutorial (5 hours ago) +<span style="color:green;"> * </span><span style="color:green;">tutorialtypos </span> (5 hours ago) + 4.3compat (4 days ago) + prev-next (12 days ago) + obsfatefixes (2 weeks ago) + more-output (3 weeks ago) + obsmarkerbitfield (2 months ago) + obscache (2 months ago) + evolvecolor (2 months ago) + obsrangecacheiterative (2 months ago) + stack_unstable_bug (2 months ago) + doc (3 months ago) + split (3 months ago) + import-checker (4 months ago) + packaging (4 months ago) +</pre> + +#### Topics verbose + +<pre class="shell_output"> +$> hg topics --verbose + 4.3compat (on branch: default, 1 changesets, <span style="color:teal;">43 behind</span>) + doc (on branch: stable, 1 changesets, <span style="color:teal;">415 behind</span>) + evolvecolor (on branch: default, 1 changesets, <span style="color:teal;">369 behind</span>) + import-checker (on branch: default, 1 changesets, <span style="color:teal;">637 behind</span>) + more-output (on branch: default, 1 changesets, <span style="color:teal;">104 behind</span>) + obscache (on branch: default, 1 changesets, <span style="color:teal;">325 behind</span>) + obsfatefixes (on branch: default, 1 changesets, <span style="color:teal;">82 behind</span>) + obsmarkerbitfield (on branch: default, 1 changesets, <span style="color:teal;">324 behind</span>) + obsrangecacheiterative (on branch: default, 1 changesets, <span style="color:teal;">461 behind</span>) + packaging (on branch: default, 1 changesets, <span style="color:teal;">2521 behind</span>) + prev-next (on branch: default, 4 changesets, <span style="color:teal;">72 behind</span>) + split (on branch: default, 1 changesets, <span style="color:teal;">492 behind</span>) + stack_unstable_bug (on branch: default, 1 changesets, <span style="color:teal;">474 behind</span>) + tutorial (on branch: default, 2 changesets, <span style="color:teal;">492 behind</span>) +<span style="color:green;"> * </span><span style="color:green;">tutorialtypos </span> (on branch: default, 3 changesets, <span style="color:red;">1 troubled</span>, <span style="color:olive;">2 heads</span>, <span style="color:teal;">2 behind</span>) +</pre> + +#### Log + +<pre> +$ hg log -G --hidden -T '{node|short}\n{obsfate}\n' +@ c55cb2ee8a91 +| +o 23abfc79b7ce +| +| o 4302274177b9 <span style="color:red;">(unstable)</span> +| | +| <span style="color:grey;">x fba593aaaa10</span> +|/ rewritten as c55cb2ee8a91; +o 2ff53d8bf7d7 +</pre> + +#### Evolve --list + +<pre> +$> hg evolve --list +<span style="color:gold;">9ac0d376e01c</span>: changelog: introduce a 'tiprev' method + <span style="color:red;">unstable</span>: <span style="color:grey;">52ec3072fe46</span> (obsolete parent) + +<span style="color:gold;">3efd3eab9860</span>: changelog: use 'tiprev()' in 'tip()' + <span style="color:red;">unstable</span>: <span style="color:red;">9ac0d376e01c</span> (unstable parent) +</pre> + +(see also `hg evolve --list --rev`) + +#### Obslog + +<pre> +$> hg obslog +@ <span style="color:olive;">c55cb2ee8a91</span> <span style="color:blue;">(4)</span> A2 +| +| o <span style="color:olive;">4302274177b9</span> <span style="color:blue;">(2)</span> A1 +|/ +x <span style="color:olive;">fba593aaaa10</span> <span style="color:blue;">(1)</span> A + rewritten(description, parent) as <span style="color:olive;">c55cb2ee8a91</span> + by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> + <span style="color:teal;">(Thu Jun 22 00:00:29 2017 +0200)</span> + rewritten(description) as <span style="color:olive;">4302274177b9</span> + by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> + <span style="color:teal;">(Thu Jun 22 00:00:28 2017 +0200)</span> + +</pre> + +#### Obslog --patch + +<pre> +$> hg obslog -p +@ <span style="color:olive;">f6b1dded9e95</span> <span style="color:blue;">(2)</span> A1 +| +x <span style="color:olive;">364e589e2bac</span> <span style="color:blue;">(1)</span> A + rewritten(description, parent) as <span style="color:olive;">a6be771bedcf</span> + by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> + <span style="color:teal;">(Thu Jun 22 00:00:29 2017 +0200)</span> + (No patch available yet, changesets rebased) + rewritten(description) as <span style="color:olive;">f6b1dded9e95</span> + by <span style="color:green;">Boris Feld <boris.feld@octobus.net></span> + <span style="color:teal;">(Thu Jun 22 00:00:28 2017 +0200)</span> + --- a/364e589e2bac-changeset-description + +++ b/f6b1dded9e95-changeset-description + @@ -1,1 +1,1 @@ + -A + +A1 +</pre> + +#### Journal + +<pre> +$> hg journal +previous locations of '.': +2fb6d364d453 commit --amend -m Step1 +701fb5d73e07 update --rev t1 +ae11635effb7 commit -A -m Step2 +701fb5d73e07 commit -A -m Step +</pre> + +## Semantic + +#### Use the right commands! + +<img src="https://media.giphy.com/media/uRb2p09vY8lEs/giphy.gif"> + +#### smart commands + +<table> +<tr> +<th>Operation</th> +<th>command</th> +</tr> +<tr> +<td>Modify</td> +<td>`hg amend`<br></td> +</tr> +<tr> +<td>Remove</td> +<td>`hg prune`<br></td> +</tr> +<tr> +<td>Move</td> +<td>`hg grab`<br></td> +</tr> +<tr> +<td>Split</td> +<td>`hg split`<br></td> +</tr> +<tr> +<td>Fold</td> +<td>`hg fold`<br></td> +</tr> +</table> + + +## Troubles + +#### Evolution + +* Unlock powerful unique features + +* Hide **most** of the complexity + +* Help with unstable situations + + - Automatic detection + + - Automated resolution `hg help evolve` + +#### instability + +(currently: *troubles*) + +* **Orphans:** ancestors were rewritten + +* **Divergence:** branching in evolutions + + - Content-divergence: independent rewrites + + - Phase-divergence: older version got published + +## Conclusion + +#### Work in progress + +* Concepts are solid +* Implementation in progress +* Common case works fine +* Some rough edges +* Feedback → priority + +#### Use Evolution Today + +install `hg-evolve` + +<pre> +[extensions] +evolve= +topic= ## provides hg stack +</pre> + +#### Helps + +* Mailing-list: `evolve-testers@mercurial-scm.org` +* IRC channel: `#mercurial` + +#### Documentation + +* Documentation: <br/><small><https://www.mercurial-scm.org/doc/evolution/index.html></small> +* Wiki: <br/><small><https://www.mercurial-scm.org/wiki/EvolveExtension></small> + +## Conclusion + +#### Rewrite all the things! + +<img src="https://cdn.meme.am/cache/instances/folder258/500x/54913258.jpg"> + +#### Safety first! + +<img src="https://media.giphy.com/media/46vrhWWOJ4wHC/giphy.gif"> + +## extra - Troubles + +#### Obsolete + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + + node[group=main]; + Root -> New; + node[group=obsolete]; + Root -> Obsolete; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Obsolete -> New; + + Obsolete [fillcolor="#DFDFFF"]; + Root[shape="circle"]; + } +~~~ + +#### Unstable + +Now called `orphan` + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + node[group=main]; + Root -> New; + node[group=obsolete]; + Root -> Obsolete -> Unstable; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Obsolete -> New; + + Obsolete [fillcolor="#DFDFFF"]; + Unstable [fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +#### Bumped + +Now called `Phase-divergent` + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + node[group=main]; + Root -> New; + node[group=obsolete]; + Root -> Obsolete; + node[group=bumped]; + Root -> Bumped; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Obsolete -> New; + Obsolete -> Bumped; + + New [shape="circle"]; + Obsolete [fillcolor="#DFDFFF"]; + Bumped [fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +#### Divergent + +Now called `Content-divergent` + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, style="filled", width=1, height=1, fillcolor="#7F7FFF", shape="pentagon"]; + + Root -> Base; + Root -> Divergent1; + Root -> Divergent2; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + Base -> Divergent1; + Base -> Divergent2; + + Base [shape="pentagon", fillcolor="#DFDFFF"]; + Divergent1 [fillcolor="#FF3535"]; + Divergent2 [fillcolor="#FF3535"]; + Root[shape="circle"]; + } +~~~ + +## extra-commands + +#### Amend + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A"; + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> +To amend A: + + hg amend -m 'A1' +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A1"; + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A1"; + Root [shape="circle"]; + } +~~~ +</div> +</div> + +#### Prune + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=main]; + Root -> "A"; + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> + +To prune A: + + hg prune -r "desc(A)" +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + Root [shape="circle"]; + + // Revisions + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + } +~~~ +</div> +</div> + +#### Rebase + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> B; + node[group=main]; + Root -> "A"; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> + +In order to rebase A on top of B; + + hg rebase -r "desc(A)" -d "desc(B)" + +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> B -> "A'"; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> "A"; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "A'"; + + Root [shape="circle"]; + } +~~~ +</div> +</div> + +#### Fold + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 15%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> A -> B; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 70%'> + +To fold A and B: + + hg fold -r "desc(A)" -r "desc(B)" -m "C" + +</div> + +<div class='right' style='order:2; width: 15%'> + +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> C; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> A -> B; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "C"; + "B" -> "C"; + + Root [shape="circle"]; + } +~~~ + +</div> +</div> + +#### Split + +<div class='graph' style='display: flex ;align-items: stretch ;flex-flow: row wrap ; align-items: center;'> +<div class='left' style='order:1; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> A; + + Root [shape="circle"]; + } +~~~ +</div> + +<div class="middle" style='order:2; width: 60%'> + +Split in two: + + hg split -r "desc(A)" +</div> + +<div class='right' style='order:2; width: 20%'> +~~~graphviz + digraph G { + rankdir="BT"; + graph[splines=polyline]; + node[fixedsize=true, width=1, height=1, style="filled", fillcolor="#7F7FFF", shape="pentagon"]; + + // Revisions + node[group=branch]; + Root -> B -> C; + + node[group=obsolete, style="dotted, filled", fillcolor="#DFDFFF"]; + Root -> A; + + // Obsolescence links + edge[dir=back, style=dotted, arrowtail=dot]; + "A" -> "C"; + "A" -> "B"; + + Root [shape="circle"]; + } +~~~ +</div> +</div> + -->
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/standalone.html Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,98 @@ +<!DOCTYPE html> +<html $if(lang)$ lang="$lang$" $endif$ dir="ltr"> + + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>$if(title)$$title$$endif$</title> + +$if(template_css)$ +<link rel="stylesheet" href="$template_css$"> +$else$ +<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.26.4/css/uikit.gradient.css"> +$endif$ + + <link rel="stylesheet" href="style.css"> + <script src="https://code.jquery.com/jquery-2.2.1.min.js"></script> + <script src="uikit.js"></script> + <script src="scripts.js"></script> + <script src="jquery.sticky-kit.js "></script> + + <meta name="generator" content="pandoc-uikit" /> + $for(author-meta)$ + <meta name="author" content="$author-meta$" /> + $endfor$ + $if(date-meta)$ + <meta name="date" content="$date-meta$" /> + $endif$ + <title>$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$</title> + <style type="text/css">code{white-space: pre;}</style> + $if(quotes)$ + <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style> + $endif$ + $if(highlighting-css)$ + <style type="text/css"> + $highlighting-css$ + </style> + $endif$ + $for(css)$ + <link rel="stylesheet" href="$css$" $if(html5)$$else$type="text/css" $endif$/> + $endfor$ + $if(math)$ + $math$ + $endif$ + $for(header-includes)$ + $header-includes$ + $endfor$ + </head> + + <body> + + + <div class="uk-container uk-container-center uk-margin-top uk-margin-large-bottom"> + + $if(title)$ + <div class="uk-grid" data-uk-grid-margin> + <div class="uk-width-1-1"> + <h1 class="uk-heading-large">$title$</h1> + $if(date)$ + <h3 class="uk-heading-large">$date$</p></h3> + $endif$ + $for(author)$ + <p class="uk-text-large">$author$</p> + $endfor$ + </div> + </div> + $endif$ + + <div class="uk-grid" data-uk-grid-margin > + <div class="uk-width-medium-1-4"> + <div class="uk-overflow-container" data-uk-sticky="{top:25,media: 768}"> + <div class="uk-panel uk-panel-box menu-begin" > + + $if(toc)$ + $toc$ + $endif$ + + </div> + </div> + </div> + + <div class="uk-width-medium-3-4"> +$body$ + </div> + </div> +$if(analytics)$ + <script> + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); + + ga('create', '$analytics$', 'auto'); + ga('send', 'pageview'); +$endif$ + + </div> + </body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/style.css Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,48 @@ + +/* +.uk-overflow-container { + overflow-y: scroll; + top: 0; + bottom: 0; + + +}*/ +table { + min-width: 100% +} + +.video-js { + min-width:100%; + max-width:100%; + max-height: 100%; +} + +.vjs-fullscreen { + padding-top: 0px +} + +::-webkit-scrollbar { + width: 12px; /* for vertical scrollbars */ + height: 12px; /* for horizontal scrollbars */ +} + +::-webkit-scrollbar-track { + background: rgba(0, 0, 0, 0.1); +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.5); +} + + +.uk-overflow-container { + overflow-y: scroll; + top: 0; + bottom: 0; +} + +em { + color:#666; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/test-training.t Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,3087 @@ +===================== +Evolve/Topic Training +===================== + +.. Various setup + + $ . $TESTDIR/testlib/common.sh + $ cat >> $HGRCPATH << EOF + > [ui] + > interactive = true + > [extensions] + > rebase= + > evolve= + > topic= + > docgraph= + > histedit= + > + > EOF + +Create the base repo +-------------------- + + $ hg init $TESTTMP/base + $ cd $TESTTMP/base + +Setup the hgrc + $ cat > .hg/hgrc << EOF + > [paths] + > default = https://bitbucket.org/octobus/evolve_training_repo + > [ui] + > interactive = true + > interface = text + > username = Boris Feld <boris.feld@octobus.net> + > tweakdefault = true + > [extensions] + > rebase= + > evolve= + > topic= + > histedit= + > [phases] + > publish = False + > + > EOF + +0:ROOT + + $ touch README + $ cp .hg/hgrc hgrc + $ hg add README hgrc + $ hg commit -m "ROOT" -d "Thu Dec 07 11:26:05 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + $ hg phase -p . + +1:amend + + $ hg branch typo + marked working directory as branch typo + (branches are permanent and global, did you want a bookmark?) + $ touch fix-bug + $ hg add fix-bug + $ hg commit -m "Fx bug" -d "Thu Dec 07 11:26:53 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + +2-6:rebase + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ hg branch build/v2 + marked working directory as branch build/v2 + $ mkdir v2 + $ touch v2/README + $ hg add v2/README + $ hg commit -m "First commit on build/v2" -d "Thu Dec 07 16:45:07 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ hg branch build/linuxsupport-v2 + marked working directory as branch build/linuxsupport-v2 + $ touch v2/LINUX + $ hg add v2/LINUX + $ hg commit -m "First commit on build/linuxsupport-v2" -d "Thu Dec 07 16:46:32 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ echo "Instructions for linux" > v2/LINUX + $ hg commit -m "Second commit on build/linuxsupport-v2." -d "Mon Dec 11 11:20:24 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ touch v2/Makefile.linux + $ hg add v2/Makefile.linux + $ hg commit -m "Third commit on build/linuxsupport-v2" -d "Mon Dec 11 11:21:02 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ hg up "build/v2" + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ touch v2/WINDOWS + $ hg add v2/WINDOWS + $ hg commit -m "New commit on build/v2" -d "Mon Dec 11 11:22:16 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + +7-8:amend-extract + + $ hg up 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg branch amend-extract + marked working directory as branch amend-extract + $ cat >> fileextract << EOF + > # The file dedicated to be extracted + > + > 1 + > 2 + > 3 + > 4 + > 5 + > 6 + > 7 + > 8 + > 9 + > 10 + > + > EOF + $ hg add fileextract + $ hg commit -m "Base file" -d "Fri Dec 08 15:04:09 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ echo "badbadfile" > badfile + $ hg add badfile + $ cat > fileextract << EOF + > # The file dedicated to be extracted + > + > 0 + > 1 + > 2 + > 3 + > 4 + > 5 + > 6 + > 7 + > 8 + > 9 + > 10 + > 42 + > + > EOF + $ hg commit -m "Commit to be extracted" -d "Fri Dec 08 15:28:46 2017 +0100" -u "Bad User" + +9: prune + + $ hg up 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ hg branch prune + marked working directory as branch prune + $ touch filetoprune + $ hg add filetoprune + $ hg commit -m "Commit to prune" -d "Fri Dec 08 16:12:23 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ hg export + # HG changeset patch + # User Boris Feld <boris.feld@octobus.net> + # Date 1512745943 -3600 + # Fri Dec 08 16:12:23 2017 +0100 + # Branch prune + # Node ID 324b72ebbb217eb34975c65c794a7d9408a88675 + # Parent d2eb2ac6a5bd73b2cc78fca3489488b2b0fdf8b1 + Commit to prune + +10-12: fold + + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg branch fold + marked working directory as branch fold + $ mkdir test + $ echo "assert 42 = 0" > test/unit + $ hg add test/unit + $ hg commit -m "add a test" -d "Fri Dec 08 16:49:45 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ echo "assert 42 = 43" > test/unit + $ hg commit -m "Fix the test" -d "Fri Dec 08 16:50:17 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ echo "assert 42 = 42" > test/unit + $ hg commit -m "Really fix the test" -d "Fri Dec 08 16:50:38 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ hg export + # HG changeset patch + # User Boris Feld <boris.feld@octobus.net> + # Date 1512748238 -3600 + # Fri Dec 08 16:50:38 2017 +0100 + # Branch fold + # Node ID 966df9f031c13cd37c685b6c2a2e7423935cef56 + # Parent b316dc02bddce9fa1f8676a0feeccdeb1bea03ae + Really fix the test + + diff -r b316dc02bddc -r 966df9f031c1 test/unit + --- a/test/unit Fri Dec 08 16:50:17 2017 +0100 + +++ b/test/unit Fri Dec 08 16:50:38 2017 +0100 + @@ -1,1 +1,1 @@ + -assert 42 = 43 + +assert 42 = 42 + +13: split + + $ hg up 0 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg branch split + marked working directory as branch split + $ mkdir src + $ touch src/A src/B src/C + $ hg add src/* + $ hg commit -m "To be splitted" -d "Fri Dec 08 17:33:15 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + +14-16: histedit + + $ hg up 0 + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ hg branch histedit + marked working directory as branch histedit + + $ hg commit -m "First commit on histedit branch" -d "Fri Dec 09 17:33:15 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ mkdir myfeature + $ touch myfeature/code + $ hg add myfeature/code + $ hg commit -m "Add code for myfeature" -d "Fri Dec 09 17:35:15 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ touch myfeature/test + $ hg add myfeature/test + $ hg commit -m "Add test for myfeature" -d "Fri Dec 09 17:37:15 2017 +0100" -u "Boris Feld <boris.feld@octobus.net>" + + $ cp -R $TESTTMP/base $TESTDIR/base-repos/init + + $ hg log -G + @ changeset: 16:1b1e58a9ed27 + | branch: histedit + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:37:15 2017 +0100 + | summary: Add test for myfeature + | + o changeset: 15:23eb6f9e4c51 + | branch: histedit + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:35:15 2017 +0100 + | summary: Add code for myfeature + | + o changeset: 14:d102c718e607 + | branch: histedit + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:33:15 2017 +0100 + | summary: First commit on histedit branch + | + | o changeset: 13:5d5029b9daed + |/ branch: split + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 17:33:15 2017 +0100 + | summary: To be splitted + | + | o changeset: 12:966df9f031c1 + | | branch: fold + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Fri Dec 08 16:50:38 2017 +0100 + | | summary: Really fix the test + | | + | o changeset: 11:b316dc02bddc + | | branch: fold + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Fri Dec 08 16:50:17 2017 +0100 + | | summary: Fix the test + | | + | o changeset: 10:03174536bb2a + |/ branch: fold + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:49:45 2017 +0100 + | summary: add a test + | + | o changeset: 9:324b72ebbb21 + |/ branch: prune + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:12:23 2017 +0100 + | summary: Commit to prune + | + | o changeset: 8:e288d12d5e96 + | | branch: amend-extract + | | user: Bad User + | | date: Fri Dec 08 15:28:46 2017 +0100 + | | summary: Commit to be extracted + | | + | o changeset: 7:4ae0d1de7a58 + |/ branch: amend-extract + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 15:04:09 2017 +0100 + | summary: Base file + | + | o changeset: 6:0e694460372e + | | branch: build/v2 + | | parent: 2:f3bd0ab4ee87 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:22:16 2017 +0100 + | | summary: New commit on build/v2 + | | + | | o changeset: 5:39e9774ab30b + | | | branch: build/linuxsupport-v2 + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Mon Dec 11 11:21:02 2017 +0100 + | | | summary: Third commit on build/linuxsupport-v2 + | | | + | | o changeset: 4:5ad93176b041 + | | | branch: build/linuxsupport-v2 + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Mon Dec 11 11:20:24 2017 +0100 + | | | summary: Second commit on build/linuxsupport-v2. + | | | + | | o changeset: 3:424916b62f4c + | |/ branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Thu Dec 07 16:46:32 2017 +0100 + | | summary: First commit on build/linuxsupport-v2 + | | + | o changeset: 2:f3bd0ab4ee87 + |/ branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + | o changeset: 1:5d48a444aba7 + |/ branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fx bug + | + o changeset: 0:d2eb2ac6a5bd + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + +Amend +----- + + $ cp -R $TESTTMP/base $TESTTMP/evolve_training_repo + $ cd $TESTTMP/evolve_training_repo + + $ hg update typo + 1 files updated, 0 files merged, 2 files removed, 0 files unresolved + +BEFORE + $ hg log -G -v -r "::typo" -T "{rev} {phase}\n" + @ 1 draft + | + o 0 public + + $ graph $TESTDIR/graphs/fix-bug-1.dot -r '::typo' -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/fix-bug-1.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 1 [fillcolor="#7F7FFF", + fixedsize=true, + group=typo, + height=1, + label="5d48a444", + pin=true, + pos="2,1!", + shape=circle, + style=filled, + width=1]; + 0 -> 1 [penwidth=2.0]; + } + + $ html_output $TESTDIR/output/fix-a-bug-base.log log -G -r "::typo" + @ <span style="color:olive;">changeset: 1:5d48a444aba7</span> + | branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fx bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ html_output $TESTDIR/output/fix-a-bug-base-summary.log summary + <span style="color:olive;">parent: 1:5d48a444aba7 </span> + Fx bug + branch: typo + commit: (clean) + update: (current) + phases: 16 draft + +Commit with Evolve + $ hg commit --amend --message "Fix bug" + + $ html_output $TESTDIR/output/amend-after.log log -G -r "::typo" + @ <span style="color:olive;">changeset: 17:708369dc1bfe</span> + | branch: typo + | tag: tip + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fix bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ html_output $TESTDIR/output/fix-a-bug-with-evolve-2.log log -G -r "::branch(typo)" --hidden + @ <span style="color:olive;">changeset: 17:708369dc1bfe</span> + | branch: typo + | tag: tip + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fix bug + | + | x <span style="color:olive;">changeset: 1:5d48a444aba7</span> + |/ branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | obsolete: reworded using amend as 17:708369dc1bfe + | summary: Fx bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + +Mark everything as public for the graph + + $ graph $TESTDIR/graphs/fix-bug-2.dot -r '::typo' -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/fix-bug-2.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 17 [fillcolor="#7F7FFF", + fixedsize=true, + group=typo, + height=1, + label="708369dc", + pin=true, + pos="2,17!", + shape=circle, + style=filled, + width=1]; + 0 -> 17 [penwidth=2.0]; + } + + $ graph $TESTDIR/graphs/fix-bug-3.dot -r '::branch(typo)' --hidden -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/fix-bug-3.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 1 [fillcolor="#DFDFFF", + fixedsize=true, + group=typo_extinct, + height=1, + label="5d48a444", + pin=true, + pos="2,1!", + shape=circle, + style="dotted, filled", + width=1]; + 0 -> 1 [penwidth=2.0]; + 17 [fillcolor="#7F7FFF", + fixedsize=true, + group=typo, + height=1, + label="708369dc", + pin=true, + pos="3,17!", + shape=circle, + style=filled, + width=1]; + 0 -> 17 [penwidth=2.0]; + 1 -> 17 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + } + + $ html_output $TESTDIR/output/amend-after.log log -G -r "::typo" + @ <span style="color:olive;">changeset: 17:708369dc1bfe</span> + | branch: typo + | tag: tip + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fix bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/amend-obslog-after.log obslog -G -r "typo" + @ <span style="color:olive;">708369dc1bfe</span> <span style="color:blue;">(17)</span> Fix bug + | + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ html_output $TESTDIR/output/amend-obslog-patch-after.log obslog -G -r "typo" --patch + @ <span style="color:olive;">708369dc1bfe</span> <span style="color:blue;">(17)</span> Fix bug + | + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + --- a/5d48a444aba7-changeset-description + +++ b/708369dc1bfe-changeset-description + @@ -1,1 +1,1 @@ + -Fx bug + +Fix bug + + + $ html_output $TESTDIR/output/amend-obslog-all-after.log obslog --all -G -r "precursors(typo)" --hidden + @ <span style="color:olive;">708369dc1bfe</span> <span style="color:blue;">(17)</span> Fix bug + | + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + +Rebase +------ + +Before + $ hg up build/linuxsupport-v2 + 3 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/rebase-before.log log -G -r '::desc(v2)' + o <span style="color:olive;">changeset: 6:0e694460372e</span> + | branch: build/v2 + | parent: 2:f3bd0ab4ee87 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:22:16 2017 +0100 + | summary: New commit on build/v2 + | + | @ <span style="color:olive;">changeset: 5:39e9774ab30b</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:21:02 2017 +0100 + | | summary: Third commit on build/linuxsupport-v2 + | | + | o <span style="color:olive;">changeset: 4:5ad93176b041</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:20:24 2017 +0100 + | | summary: Second commit on build/linuxsupport-v2. + | | + | o <span style="color:olive;">changeset: 3:424916b62f4c</span> + |/ branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:46:32 2017 +0100 + | summary: First commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 2:f3bd0ab4ee87</span> + | branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ graph $TESTDIR/graphs/rebase-before.dot -r '::desc(v2)' -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/rebase-before.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 2 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/v2", + height=1, + label=f3bd0ab4, + pin=true, + pos="2,2!", + shape=circle, + style=filled, + width=1]; + 0 -> 2 [penwidth=2.0]; + 3 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="424916b6", + pin=true, + pos="3,3!", + shape=circle, + style=filled, + width=1]; + 2 -> 3 [penwidth=2.0]; + 6 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/v2", + height=1, + label="0e694460", + pin=true, + pos="2,6!", + shape=circle, + style=filled, + width=1]; + 2 -> 6 [penwidth=2.0]; + 4 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="5ad93176", + pin=true, + pos="3,4!", + shape=circle, + style=filled, + width=1]; + 3 -> 4 [penwidth=2.0]; + 5 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="39e9774a", + pin=true, + pos="3,5!", + shape=circle, + style=filled, + width=1]; + 4 -> 5 [penwidth=2.0]; + } + +Do the rebase + + $ html_output $TESTDIR/output/rebase.log rebase -r "branch(build/linuxsupport-v2)" --dest build/v2 --keepbranches + rebasing 3:424916b62f4c "First commit on build/linuxsupport-v2" + rebasing 4:5ad93176b041 "Second commit on build/linuxsupport-v2." + rebasing 5:39e9774ab30b "Third commit on build/linuxsupport-v2" + +After the rebase + + $ html_output $TESTDIR/output/rebase-after.log log -G -r '::desc(v2)' + @ <span style="color:olive;">changeset: 20:3d2c8a2356a2</span> + | branch: build/linuxsupport-v2 + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:21:02 2017 +0100 + | summary: Third commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 19:4686378320d7</span> + | branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | summary: Second commit on build/linuxsupport-v2. + | + o <span style="color:olive;">changeset: 18:7b62ce2c283e</span> + | branch: build/linuxsupport-v2 + | parent: 6:0e694460372e + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:46:32 2017 +0100 + | summary: First commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 6:0e694460372e</span> + | branch: build/v2 + | parent: 2:f3bd0ab4ee87 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:22:16 2017 +0100 + | summary: New commit on build/v2 + | + o <span style="color:olive;">changeset: 2:f3bd0ab4ee87</span> + | branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ html_output $TESTDIR/output/rebase-after-hidden.log log -G -r '::desc(v2)' --hidden + @ <span style="color:olive;">changeset: 20:3d2c8a2356a2</span> + | branch: build/linuxsupport-v2 + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:21:02 2017 +0100 + | summary: Third commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 19:4686378320d7</span> + | branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | summary: Second commit on build/linuxsupport-v2. + | + o <span style="color:olive;">changeset: 18:7b62ce2c283e</span> + | branch: build/linuxsupport-v2 + | parent: 6:0e694460372e + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:46:32 2017 +0100 + | summary: First commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 6:0e694460372e</span> + | branch: build/v2 + | parent: 2:f3bd0ab4ee87 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:22:16 2017 +0100 + | summary: New commit on build/v2 + | + | x <span style="color:olive;">changeset: 5:39e9774ab30b</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:21:02 2017 +0100 + | | obsolete: rebased using rebase as 20:3d2c8a2356a2 + | | summary: Third commit on build/linuxsupport-v2 + | | + | x <span style="color:olive;">changeset: 4:5ad93176b041</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:20:24 2017 +0100 + | | obsolete: rebased using rebase as 19:4686378320d7 + | | summary: Second commit on build/linuxsupport-v2. + | | + | x <span style="color:olive;">changeset: 3:424916b62f4c</span> + |/ branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:46:32 2017 +0100 + | obsolete: rebased using rebase as 18:7b62ce2c283e + | summary: First commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 2:f3bd0ab4ee87</span> + | branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/rebase-obslog-after.log obslog -r "build/linuxsupport-v2" + @ <span style="color:olive;">3d2c8a2356a2</span> <span style="color:blue;">(20)</span> Third commit on build/linuxsupport-v2 + | + x <span style="color:olive;">39e9774ab30b</span> <span style="color:blue;">(5)</span> Third commit on build/linuxsupport-v2 + rewritten(parent) as <span style="color:olive;">3d2c8a2356a2</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ graph $TESTDIR/graphs/rebase-after.dot -r '::desc(v2)' -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/rebase-after.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 2 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/v2", + height=1, + label=f3bd0ab4, + pin=true, + pos="2,2!", + shape=circle, + style=filled, + width=1]; + 0 -> 2 [penwidth=2.0]; + 6 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/v2", + height=1, + label="0e694460", + pin=true, + pos="2,6!", + shape=circle, + style=filled, + width=1]; + 2 -> 6 [penwidth=2.0]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="7b62ce2c", + pin=true, + pos="3,18!", + shape=circle, + style=filled, + width=1]; + 6 -> 18 [penwidth=2.0]; + 19 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label=46863783, + pin=true, + pos="3,19!", + shape=circle, + style=filled, + width=1]; + 18 -> 19 [penwidth=2.0]; + 20 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="3d2c8a23", + pin=true, + pos="3,20!", + shape=circle, + style=filled, + width=1]; + 19 -> 20 [penwidth=2.0]; + } + + $ graph $TESTDIR/graphs/rebase-after-hidden.dot -r '::desc(v2)' -T "{shortest(node, 8)}" --hidden --public=yes + Wrote */graphs/rebase-after-hidden.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 2 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/v2", + height=1, + label=f3bd0ab4, + pin=true, + pos="2,2!", + shape=circle, + style=filled, + width=1]; + 0 -> 2 [penwidth=2.0]; + 3 [fillcolor="#DFDFFF", + fixedsize=true, + group="build/linuxsupport-v2_extinct", + height=1, + label="424916b6", + pin=true, + pos="3,3!", + shape=circle, + style="dotted, filled", + width=1]; + 2 -> 3 [penwidth=2.0]; + 6 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/v2", + height=1, + label="0e694460", + pin=true, + pos="2,6!", + shape=circle, + style=filled, + width=1]; + 2 -> 6 [penwidth=2.0]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="7b62ce2c", + pin=true, + pos="4,18!", + shape=circle, + style=filled, + width=1]; + 3 -> 18 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 4 [fillcolor="#DFDFFF", + fixedsize=true, + group="build/linuxsupport-v2_extinct", + height=1, + label="5ad93176", + pin=true, + pos="3,4!", + shape=circle, + style="dotted, filled", + width=1]; + 3 -> 4 [penwidth=2.0]; + 19 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label=46863783, + pin=true, + pos="4,19!", + shape=circle, + style=filled, + width=1]; + 18 -> 19 [penwidth=2.0]; + 4 -> 19 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 5 [fillcolor="#DFDFFF", + fixedsize=true, + group="build/linuxsupport-v2_extinct", + height=1, + label="39e9774a", + pin=true, + pos="3,5!", + shape=circle, + style="dotted, filled", + width=1]; + 4 -> 5 [penwidth=2.0]; + 20 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="3d2c8a23", + pin=true, + pos="4,20!", + shape=circle, + style=filled, + width=1]; + 19 -> 20 [penwidth=2.0]; + 5 -> 20 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 6 -> 18 [penwidth=2.0]; + } + +Under the hood +-------------- + + $ cp -R $TESTTMP/evolve_training_repo $TESTDIR/base-repos/behind-the-hoods/ + +Amend + + $ html_output $TESTDIR/output/behind-the-hood-amend-before-hash-hidden.log log -G -r "::precursors(typo)" --hidden + x <span style="color:olive;">changeset: 1:5d48a444aba7</span> + | branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | obsolete: reworded using amend as 17:708369dc1bfe + | summary: Fx bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + +XXX Remove the command line to avoid showing precursors and hidden revset + + $ tail -n +2 $TESTDIR/output/behind-the-hood-amend-before-hash-hidden.log | tee $TESTDIR/output/behind-the-hood-amend-before-hash-hidden.log + x <span style="color:olive;">changeset: 1:5d48a444aba7</span> + | branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | obsolete: reworded using amend as 17:708369dc1bfe + | summary: Fx bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/behind-the-hood-amend-after.log log -G -r "::typo" + o <span style="color:olive;">changeset: 17:708369dc1bfe</span> + | branch: typo + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fix bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ html_output $TESTDIR/output/under-the-hood-amend-after-log-hidden.log log -G -r "::branch(typo)" --hidden + o <span style="color:olive;">changeset: 17:708369dc1bfe</span> + | branch: typo + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | summary: Fix bug + | + | x <span style="color:olive;">changeset: 1:5d48a444aba7</span> + |/ branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | obsolete: reworded using amend as 17:708369dc1bfe + | summary: Fx bug + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/under-the-hood-amend-after-obslog-patch.log obslog -G -r typo --patch + o <span style="color:olive;">708369dc1bfe</span> <span style="color:blue;">(17)</span> Fix bug + | + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + --- a/5d48a444aba7-changeset-description + +++ b/708369dc1bfe-changeset-description + @@ -1,1 +1,1 @@ + -Fx bug + +Fix bug + + + $ html_output $TESTDIR/output/under-the-hood-amend-after-obslog.log obslog -G -r typo + o <span style="color:olive;">708369dc1bfe</span> <span style="color:blue;">(17)</span> Fix bug + | + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ html_output $TESTDIR/output/under-the-hood-amend-after-obslog-no-all.log obslog -G -r "5d48a444aba7" --hidden + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ html_output $TESTDIR/output/under-the-hood-amend-after-obslog-all.log obslog -G -r "5d48a444aba7" --hidden --all + o <span style="color:olive;">708369dc1bfe</span> <span style="color:blue;">(17)</span> Fix bug + | + x <span style="color:olive;">5d48a444aba7</span> <span style="color:blue;">(1)</span> Fx bug + rewritten(description) as <span style="color:olive;">708369dc1bfe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + + $ html_output $TESTDIR/output/under-the-hood-rebase-after-obslog.log obslog -r build/linuxsupport-v2 + @ <span style="color:olive;">3d2c8a2356a2</span> <span style="color:blue;">(20)</span> Third commit on build/linuxsupport-v2 + | + x <span style="color:olive;">39e9774ab30b</span> <span style="color:blue;">(5)</span> Third commit on build/linuxsupport-v2 + rewritten(parent) as <span style="color:olive;">3d2c8a2356a2</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ html_output $TESTDIR/output/under-the-hood-rebase-after-obslog-branch.log obslog -r "branch('build/linuxsupport-v2')" + @ <span style="color:olive;">3d2c8a2356a2</span> <span style="color:blue;">(20)</span> Third commit on build/linuxsupport-v2 + | + | o <span style="color:olive;">4686378320d7</span> <span style="color:blue;">(19)</span> Second commit on build/linuxsupport-v2. + | | + | | o <span style="color:olive;">7b62ce2c283e</span> <span style="color:blue;">(18)</span> First commit on build/linuxsupport-v2 + | | | + x | | <span style="color:olive;">39e9774ab30b</span> <span style="color:blue;">(5)</span> Third commit on build/linuxsupport-v2 + / / rewritten(parent) as <span style="color:olive;">3d2c8a2356a2</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + | | + | x <span style="color:olive;">424916b62f4c</span> <span style="color:blue;">(3)</span> First commit on build/linuxsupport-v2 + | rewritten(parent) as <span style="color:olive;">7b62ce2c283e</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + | + x <span style="color:olive;">5ad93176b041</span> <span style="color:blue;">(4)</span> Second commit on build/linuxsupport-v2. + rewritten(parent) as <span style="color:olive;">4686378320d7</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + + +Rebase + + $ html_output $TESTDIR/output/behind-the-hood-rebase-before-hash-hidden.log log -G -r "::branch(build/v2) or ::precursors('build/linuxsupport-v2')" --hidden + o <span style="color:olive;">changeset: 6:0e694460372e</span> + | branch: build/v2 + | parent: 2:f3bd0ab4ee87 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:22:16 2017 +0100 + | summary: New commit on build/v2 + | + | x <span style="color:olive;">changeset: 5:39e9774ab30b</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:21:02 2017 +0100 + | | obsolete: rebased using rebase as 20:3d2c8a2356a2 + | | summary: Third commit on build/linuxsupport-v2 + | | + | x <span style="color:olive;">changeset: 4:5ad93176b041</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:20:24 2017 +0100 + | | obsolete: rebased using rebase as 19:4686378320d7 + | | summary: Second commit on build/linuxsupport-v2. + | | + | x <span style="color:olive;">changeset: 3:424916b62f4c</span> + |/ branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:46:32 2017 +0100 + | obsolete: rebased using rebase as 18:7b62ce2c283e + | summary: First commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 2:f3bd0ab4ee87</span> + | branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/behind-the-hood-rebase-after.log log -G -r "::desc(v2)" + @ <span style="color:olive;">changeset: 20:3d2c8a2356a2</span> + | branch: build/linuxsupport-v2 + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:21:02 2017 +0100 + | summary: Third commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 19:4686378320d7</span> + | branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | summary: Second commit on build/linuxsupport-v2. + | + o <span style="color:olive;">changeset: 18:7b62ce2c283e</span> + | branch: build/linuxsupport-v2 + | parent: 6:0e694460372e + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:46:32 2017 +0100 + | summary: First commit on build/linuxsupport-v2 + | + o <span style="color:olive;">changeset: 6:0e694460372e</span> + | branch: build/v2 + | parent: 2:f3bd0ab4ee87 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:22:16 2017 +0100 + | summary: New commit on build/v2 + | + o <span style="color:olive;">changeset: 2:f3bd0ab4ee87</span> + | branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + +Amend-extract +------------- + + $ hg update amend-extract + 2 files updated, 0 files merged, 4 files removed, 0 files unresolved + $ cp -R $TESTTMP/evolve_training_repo $TESTDIR/base-repos/amend-evolve-command/ + + $ html_output $TESTDIR/output/amend-extract-before.log log -G -r "::amend-extract" + @ <span style="color:olive;">changeset: 8:e288d12d5e96</span> + | branch: amend-extract + | user: Bad User + | date: Fri Dec 08 15:28:46 2017 +0100 + | summary: Commit to be extracted + | + o <span style="color:olive;">changeset: 7:4ae0d1de7a58</span> + | branch: amend-extract + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 15:04:09 2017 +0100 + | summary: Base file + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ graph $TESTDIR/graphs/amend-extract-before.dot -r '::amend-extract' -T "{shortest(node, 8)}" --hidden --public=yes + Wrote */graphs/amend-extract-before.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 7 [fillcolor="#7F7FFF", + fixedsize=true, + group="amend-extract", + height=1, + label="4ae0d1de", + pin=true, + pos="2,7!", + shape=circle, + style=filled, + width=1]; + 0 -> 7 [penwidth=2.0]; + 8 [fillcolor="#7F7FFF", + fixedsize=true, + group="amend-extract", + height=1, + label=e288d12d, + pin=true, + pos="2,8!", + shape=circle, + style=filled, + width=1]; + 7 -> 8 [penwidth=2.0]; + } + +Amend User + + $ html_output $TESTDIR/output/amend-user.log amend --user "Good User" + +After amend user + + $ html_output $TESTDIR/output/amend-user-after-export.log export . + # HG changeset patch + # User Good User + # Date 1512743326 -3600 + # Fri Dec 08 15:28:46 2017 +0100 + # Branch amend-extract + # Node ID 5935c1c3ad24c4d3338d94473261eb89a73ef0d5 + # Parent 4ae0d1de7a58916e6f24fdc42e890a71fccbd931 + Commit to be extracted + + <span style="font-weight:bold;">diff -r 4ae0d1de7a58 -r 5935c1c3ad24 badfile</span> + <span style="color:red;font-weight:bold;">--- /dev/null Thu Jan 01 00:00:00 1970 +0000</span> + <span style="color:green;font-weight:bold;">+++ b/badfile Fri Dec 08 15:28:46 2017 +0100</span> + <span style="color:purple;">@@ -0,0 +1,1 @@</span> + <span style="color:green;">+badbadfile</span> + <span style="font-weight:bold;">diff -r 4ae0d1de7a58 -r 5935c1c3ad24 fileextract</span> + <span style="color:red;font-weight:bold;">--- a/fileextract Fri Dec 08 15:04:09 2017 +0100</span> + <span style="color:green;font-weight:bold;">+++ b/fileextract Fri Dec 08 15:28:46 2017 +0100</span> + <span style="color:purple;">@@ -1,5 +1,6 @@</span> + # The file dedicated to be extracted + + <span style="color:green;">+0</span> + 1 + 2 + 3 + <span style="color:purple;">@@ -10,4 +11,5 @@</span> + 8 + 9 + 10 + <span style="color:green;">+42</span> + + +Amend extract the bad file + + $ html_output $TESTDIR/output/amend-extract-badfile.log amend --extract badfile + +After extract the bad file + + $ html_output $TESTDIR/output/amend-extract-badfile-after-export.log export -r . + # HG changeset patch + # User Good User + # Date 1512743326 -3600 + # Fri Dec 08 15:28:46 2017 +0100 + # Branch amend-extract + # Node ID 1e04751ef00ae76e357fe083f08e3f2234c3b26b + # Parent 4ae0d1de7a58916e6f24fdc42e890a71fccbd931 + Commit to be extracted + + <span style="font-weight:bold;">diff -r 4ae0d1de7a58 -r 1e04751ef00a fileextract</span> + <span style="color:red;font-weight:bold;">--- a/fileextract Fri Dec 08 15:04:09 2017 +0100</span> + <span style="color:green;font-weight:bold;">+++ b/fileextract Fri Dec 08 15:28:46 2017 +0100</span> + <span style="color:purple;">@@ -1,5 +1,6 @@</span> + # The file dedicated to be extracted + + <span style="color:green;">+0</span> + 1 + 2 + 3 + <span style="color:purple;">@@ -10,4 +11,5 @@</span> + 8 + 9 + 10 + <span style="color:green;">+42</span> + + + $ html_output $TESTDIR/output/amend-extract-badfile-after-status.log status + <span style="color:green;font-weight:bold;">A </span><span style="color:green;font-weight:bold;">badfile</span> + + $ html_output $TESTDIR/output/amend-extract-badfile-after-revert.log revert --all --no-backup + forgetting badfile + + $ rm badfile + +Amend extract the line + + $ html_output $TESTDIR/output/amend-extract.log amend --extract --interactive <<EOF + > y + > n + > y + > EOF + <span style="font-weight:bold;">diff --git a/fileextract b/fileextract</span> + 2 hunks, 2 lines changed + <span style="color:olive;">examine changes to 'fileextract'? [Ynesfdaq?]</span> y + + <span style="color:purple;">@@ -1,5 +1,6 @@</span> + # The file dedicated to be extracted + + <span style="color:green;">+0</span> + 1 + 2 + 3 + <span style="color:olive;">discard change 1/2 to 'fileextract'? [Ynesfdaq?]</span> n + + <span style="color:purple;">@@ -10,4 +11,5 @@</span> + 8 + 9 + 10 + <span style="color:green;">+42</span> + + <span style="color:olive;">discard change 2/2 to 'fileextract'? [Ynesfdaq?]</span> y + + + $ html_output $TESTDIR/output/amend-extract-after-status.log status + <span style="color:blue;font-weight:bold;">M </span><span style="color:blue;font-weight:bold;">fileextract</span> + + $ html_output $TESTDIR/output/amend-extract-after-diff.log diff + <span style="font-weight:bold;">diff -r 76ace846a3f9 fileextract</span> + <span style="color:red;font-weight:bold;">--- a/fileextract Fri Dec 08 15:28:46 2017 +0100</span> + <span style="color:green;font-weight:bold;">+++ b/fileextract Thu Jan 01 00:00:00 1970 +0000</span> + <span style="color:purple;">@@ -11,4 +11,5 @@</span> + 8 + 9 + 10 + <span style="color:green;">+42</span> + + + $ html_output $TESTDIR/output/amend-extract-after-revert.log revert --all --no-backup + reverting fileextract + + $ html_output $TESTDIR/output/amend-extract-after-obslog.log obslog -p -r . + @ <span style="color:olive;">76ace846a3f9</span> <span style="color:blue;">(24)</span> Commit to be extracted + | + x <span style="color:olive;">1e04751ef00a</span> <span style="color:blue;">(22)</span> Commit to be extracted + | rewritten(content) as <span style="color:olive;">76ace846a3f9</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + | diff -r 1e04751ef00a -r 76ace846a3f9 fileextract + | --- a/fileextract Fri Dec 08 15:28:46 2017 +0100 + | +++ b/fileextract Fri Dec 08 15:28:46 2017 +0100 + | @@ -11,5 +11,4 @@ + | 8 + | 9 + | 10 + | -42 + | + | + | + x <span style="color:olive;">5935c1c3ad24</span> <span style="color:blue;">(21)</span> Commit to be extracted + | rewritten(content) as <span style="color:olive;">1e04751ef00a</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + | diff -r 5935c1c3ad24 -r 1e04751ef00a badfile + | --- a/badfile Fri Dec 08 15:28:46 2017 +0100 + | +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 + | @@ -1,1 +0,0 @@ + | -badbadfile + | + | + x <span style="color:olive;">e288d12d5e96</span> <span style="color:blue;">(8)</span> Commit to be extracted + rewritten(user) as <span style="color:olive;">5935c1c3ad24</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + + $ graph $TESTDIR/graphs/amend-extract-after-hidden.dot -r "::desc(extracted)" -T "{shortest(node, 8)}" --hidden --public=yes + Wrote */graphs/amend-extract-after-hidden.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 7 [fillcolor="#7F7FFF", + fixedsize=true, + group="amend-extract", + height=1, + label="4ae0d1de", + pin=true, + pos="2,7!", + shape=circle, + style=filled, + width=1]; + 0 -> 7 [penwidth=2.0]; + 8 [fillcolor="#DFDFFF", + fixedsize=true, + group="amend-extract_extinct", + height=1, + label=e288d12d, + pin=true, + pos="3,8!", + shape=circle, + style="dotted, filled", + width=1]; + 7 -> 8 [penwidth=2.0]; + 21 [fillcolor="#DFDFFF", + fixedsize=true, + group="amend-extract_extinct", + height=1, + label="5935c1c3", + pin=true, + pos="3,21!", + shape=circle, + style="dotted, filled", + width=1]; + 7 -> 21 [penwidth=2.0]; + 22 [fillcolor="#DFDFFF", + fixedsize=true, + group="amend-extract_extinct", + height=1, + label="1e04751e", + pin=true, + pos="3,22!", + shape=circle, + style="dotted, filled", + width=1]; + 7 -> 22 [penwidth=2.0]; + 24 [fillcolor="#7F7FFF", + fixedsize=true, + group="amend-extract", + height=1, + label="76ace846", + pin=true, + pos="2,24!", + shape=circle, + style=filled, + width=1]; + 7 -> 24 [penwidth=2.0]; + 8 -> 21 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 21 -> 22 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 22 -> 24 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + } + +Fold +---- + + $ hg update fold + 1 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ cp -R $TESTTMP/evolve_training_repo $TESTDIR/base-repos/fold/ + + $ html_output $TESTDIR/output/fold-before.log log -r "branch(fold)" -G -p + @ <span style="color:olive;">changeset: 12:966df9f031c1</span> + | branch: fold + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:50:38 2017 +0100 + | summary: Really fix the test + | + | <span style="font-weight:bold;">diff -r b316dc02bddc -r 966df9f031c1 test/unit</span> + | <span style="color:red;font-weight:bold;">--- a/test/unit Fri Dec 08 16:50:17 2017 +0100</span> + | <span style="color:green;font-weight:bold;">+++ b/test/unit Fri Dec 08 16:50:38 2017 +0100</span> + | <span style="color:purple;">@@ -1,1 +1,1 @@</span> + | <span style="color:red;">-assert 42 = 43</span> + | <span style="color:green;">+assert 42 = 42</span> + | + o <span style="color:olive;">changeset: 11:b316dc02bddc</span> + | branch: fold + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:50:17 2017 +0100 + | summary: Fix the test + | + | <span style="font-weight:bold;">diff -r 03174536bb2a -r b316dc02bddc test/unit</span> + | <span style="color:red;font-weight:bold;">--- a/test/unit Fri Dec 08 16:49:45 2017 +0100</span> + | <span style="color:green;font-weight:bold;">+++ b/test/unit Fri Dec 08 16:50:17 2017 +0100</span> + | <span style="color:purple;">@@ -1,1 +1,1 @@</span> + | <span style="color:red;">-assert 42 = 0</span> + | <span style="color:green;">+assert 42 = 43</span> + | + o <span style="color:olive;">changeset: 10:03174536bb2a</span> + | branch: fold + ~ parent: 0:d2eb2ac6a5bd + user: Boris Feld <boris.feld@octobus.net> + date: Fri Dec 08 16:49:45 2017 +0100 + summary: add a test + + <span style="font-weight:bold;">diff -r d2eb2ac6a5bd -r 03174536bb2a test/unit</span> + <span style="color:red;font-weight:bold;">--- /dev/null Thu Jan 01 00:00:00 1970 +0000</span> + <span style="color:green;font-weight:bold;">+++ b/test/unit Fri Dec 08 16:49:45 2017 +0100</span> + <span style="color:purple;">@@ -0,0 +1,1 @@</span> + <span style="color:green;">+assert 42 = 0</span> + + + $ graph $TESTDIR/graphs/fold-before.dot -r "::fold" -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/fold-before.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 10 [fillcolor="#7F7FFF", + fixedsize=true, + group=fold, + height=1, + label=03174536, + pin=true, + pos="2,10!", + shape=circle, + style=filled, + width=1]; + 0 -> 10 [penwidth=2.0]; + 11 [fillcolor="#7F7FFF", + fixedsize=true, + group=fold, + height=1, + label=b316dc02, + pin=true, + pos="2,11!", + shape=circle, + style=filled, + width=1]; + 10 -> 11 [penwidth=2.0]; + 12 [fillcolor="#7F7FFF", + fixedsize=true, + group=fold, + height=1, + label="966df9f0", + pin=true, + pos="2,12!", + shape=circle, + style=filled, + width=1]; + 11 -> 12 [penwidth=2.0]; + } + + $ html_output $TESTDIR/output/fold.log fold --from -r "branch(fold)" -m "add a test" + 3 changesets folded + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/fold-after.log log -r "::fold" -G + @ <span style="color:olive;">changeset: 25:dab6ed4b3c75</span> + | branch: fold + | tag: tip + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add a test + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/fold-after-hidden.log log -r "::branch(fold)" -G --hidden + @ <span style="color:olive;">changeset: 25:dab6ed4b3c75</span> + | branch: fold + | tag: tip + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: add a test + | + | x <span style="color:olive;">changeset: 12:966df9f031c1</span> + | | branch: fold + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Fri Dec 08 16:50:38 2017 +0100 + | | obsolete: rewritten as 25:dab6ed4b3c75 + | | summary: Really fix the test + | | + | x <span style="color:olive;">changeset: 11:b316dc02bddc</span> + | | branch: fold + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Fri Dec 08 16:50:17 2017 +0100 + | | obsolete: rewritten as 25:dab6ed4b3c75 + | | summary: Fix the test + | | + | x <span style="color:olive;">changeset: 10:03174536bb2a</span> + |/ branch: fold + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:49:45 2017 +0100 + | obsolete: rewritten as 25:dab6ed4b3c75 + | summary: add a test + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/fold-after-hidden-obslog.log obslog -r "." + @ <span style="color:olive;">dab6ed4b3c75</span> <span style="color:blue;">(25)</span> add a test + |\ + | \ + | |\ + x | | <span style="color:olive;">03174536bb2a</span> <span style="color:blue;">(10)</span> add a test + / / rewritten(date, content) as <span style="color:olive;">dab6ed4b3c75</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + | | + x | <span style="color:olive;">966df9f031c1</span> <span style="color:blue;">(12)</span> Really fix the test + / rewritten(description, date, parent, content) as <span style="color:olive;">dab6ed4b3c75</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + | + x <span style="color:olive;">b316dc02bddc</span> <span style="color:blue;">(11)</span> Fix the test + rewritten(description, date, parent, content) as <span style="color:olive;">dab6ed4b3c75</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + + $ graph $TESTDIR/graphs/fold-after-hidden.log -r "::branch(fold)" -T "{shortest(node, 8)}" --hidden --public=yes + Wrote */graphs/fold-after-hidden.log (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 10 [fillcolor="#DFDFFF", + fixedsize=true, + group=fold_extinct, + height=1, + label=03174536, + pin=true, + pos="2,10!", + shape=circle, + style="dotted, filled", + width=1]; + 0 -> 10 [penwidth=2.0]; + 25 [fillcolor="#7F7FFF", + fixedsize=true, + group=fold, + height=1, + label=dab6ed4b, + pin=true, + pos="3,25!", + shape=circle, + style=filled, + width=1]; + 0 -> 25 [penwidth=2.0]; + 10 -> 25 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 11 [fillcolor="#DFDFFF", + fixedsize=true, + group=fold_extinct, + height=1, + label=b316dc02, + pin=true, + pos="2,11!", + shape=circle, + style="dotted, filled", + width=1]; + 10 -> 11 [penwidth=2.0]; + 11 -> 25 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 12 [fillcolor="#DFDFFF", + fixedsize=true, + group=fold_extinct, + height=1, + label="966df9f0", + pin=true, + pos="2,12!", + shape=circle, + style="dotted, filled", + width=1]; + 11 -> 12 [penwidth=2.0]; + 12 -> 25 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + } + +Split +----- + + $ hg up split + 3 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/split-before.log log -r "::split" -G + @ <span style="color:olive;">changeset: 13:5d5029b9daed</span> + | branch: split + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 17:33:15 2017 +0100 + | summary: To be splitted + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ graph $TESTDIR/graphs/split-before.dot -r "::split" -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/split-before.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 13 [fillcolor="#7F7FFF", + fixedsize=true, + group=split, + height=1, + label="5d5029b9", + pin=true, + pos="2,13!", + shape=circle, + style=filled, + width=1]; + 0 -> 13 [penwidth=2.0]; + } + + + $ html_output $TESTDIR/output/split.log split -r .<< EOF + > Y + > N + > N + > N + > Y + > N + > N + > Y + > EOF + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + adding src/A + adding src/B + adding src/C + <span style="font-weight:bold;">diff --git a/src/A b/src/A</span> + <span style="color:teal;font-weight:bold;">new file mode 100644</span> + <span style="color:olive;">examine changes to 'src/A'? [Ynesfdaq?]</span> Y + + <span style="font-weight:bold;">diff --git a/src/B b/src/B</span> + <span style="color:teal;font-weight:bold;">new file mode 100644</span> + <span style="color:olive;">examine changes to 'src/B'? [Ynesfdaq?]</span> N + + <span style="font-weight:bold;">diff --git a/src/C b/src/C</span> + <span style="color:teal;font-weight:bold;">new file mode 100644</span> + <span style="color:olive;">examine changes to 'src/C'? [Ynesfdaq?]</span> N + + created new head + <span style="color:olive;">Done splitting? [yN]</span> N + <span style="font-weight:bold;">diff --git a/src/B b/src/B</span> + <span style="color:teal;font-weight:bold;">new file mode 100644</span> + <span style="color:olive;">examine changes to 'src/B'? [Ynesfdaq?]</span> Y + + <span style="font-weight:bold;">diff --git a/src/C b/src/C</span> + <span style="color:teal;font-weight:bold;">new file mode 100644</span> + <span style="color:olive;">examine changes to 'src/C'? [Ynesfdaq?]</span> N + + <span style="color:olive;">Done splitting? [yN]</span> N + <span style="font-weight:bold;">diff --git a/src/C b/src/C</span> + <span style="color:teal;font-weight:bold;">new file mode 100644</span> + <span style="color:olive;">examine changes to 'src/C'? [Ynesfdaq?]</span> Y + + no more change to split + + $ html_output $TESTDIR/output/split-before-after.log log -r "::split" -G + @ <span style="color:olive;">changeset: 28:1b7281b1e052</span> + | branch: split + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: To be splitted + | + o <span style="color:olive;">changeset: 27:6fb7bfb44ffe</span> + | branch: split + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: To be splitted + | + o <span style="color:olive;">changeset: 26:59f0ddc4bd4b</span> + | branch: split + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: To be splitted + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ graph $TESTDIR/graphs/split-before-after-hidden.dot -r "::branch(split)" -T "{shortest(node, 8)}" --hidden --public=yes + Wrote */graphs/split-before-after-hidden.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 13 [fillcolor="#DFDFFF", + fixedsize=true, + group=split_extinct, + height=1, + label="5d5029b9", + pin=true, + pos="2,13!", + shape=circle, + style="dotted, filled", + width=1]; + 0 -> 13 [penwidth=2.0]; + 26 [fillcolor="#7F7FFF", + fixedsize=true, + group=split, + height=1, + label="59f0ddc4", + pin=true, + pos="3,26!", + shape=circle, + style=filled, + width=1]; + 0 -> 26 [penwidth=2.0]; + 13 -> 26 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 27 [fillcolor="#7F7FFF", + fixedsize=true, + group=split, + height=1, + label="6fb7bfb4", + pin=true, + pos="3,27!", + shape=circle, + style=filled, + width=1]; + 13 -> 27 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 28 [fillcolor="#7F7FFF", + fixedsize=true, + group=split, + height=1, + label="1b7281b1", + pin=true, + pos="3,28!", + shape=circle, + style=filled, + width=1]; + 13 -> 28 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 26 -> 27 [penwidth=2.0]; + 27 -> 28 [penwidth=2.0]; + } + + $ html_output $TESTDIR/output/split-after-obslog.log obslog -r . + @ <span style="color:olive;">1b7281b1e052</span> <span style="color:blue;">(28)</span> To be splitted + | + x <span style="color:olive;">5d5029b9daed</span> <span style="color:blue;">(13)</span> To be splitted + rewritten(date, parent, content) as <span style="color:olive;">1b7281b1e052, 59f0ddc4bd4b, 6fb7bfb44ffe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ html_output $TESTDIR/output/split-after-obslog-all.log obslog --all -r . + @ <span style="color:olive;">1b7281b1e052</span> <span style="color:blue;">(28)</span> To be splitted + | + | o <span style="color:olive;">59f0ddc4bd4b</span> <span style="color:blue;">(26)</span> To be splitted + |/ + | o <span style="color:olive;">6fb7bfb44ffe</span> <span style="color:blue;">(27)</span> To be splitted + |/ + x <span style="color:olive;">5d5029b9daed</span> <span style="color:blue;">(13)</span> To be splitted + rewritten(date, parent, content) as <span style="color:olive;">1b7281b1e052, 59f0ddc4bd4b, 6fb7bfb44ffe</span> by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ html_output $TESTDIR/output/split-after-log-phase.log log -G -r "::split" --template "{rev} {phase}\n" + @ 28 draft + | + o 27 draft + | + o 26 draft + | + o 0 public + + + $ html_output $TESTDIR/output/split-after-phase.log phase -r "::split" + 0: public + 26: draft + 27: draft + 28: draft + +Prune +----- + + $ hg update prune + 1 files updated, 0 files merged, 3 files removed, 0 files unresolved + + + $ html_output $TESTDIR/output/prune-before.log log -G -r "::prune" + @ <span style="color:olive;">changeset: 9:324b72ebbb21</span> + | branch: prune + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:12:23 2017 +0100 + | summary: Commit to prune + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ graph $TESTDIR/graphs/prune-before.dot -r '::prune' -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/prune-before.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 9 [fillcolor="#7F7FFF", + fixedsize=true, + group=prune, + height=1, + label="324b72eb", + pin=true, + pos="2,9!", + shape=circle, + style=filled, + width=1]; + 0 -> 9 [penwidth=2.0]; + } + + $ html_output $TESTDIR/output/prune.log prune -r . + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory now at <span style="color:olive;">d2eb2ac6a5bd</span> + 1 changesets pruned + + $ html_output $TESTDIR/output/prune-after.log log -G -r "::prune" + abort: unknown revision 'prune'! + + $ html_output $TESTDIR/output/prune-after-hidden.log log -G -r "::prune" --hidden + x <span style="color:olive;">changeset: 9:324b72ebbb21</span> + | branch: prune + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Fri Dec 08 16:12:23 2017 +0100 + | obsolete: pruned + | summary: Commit to prune + | + @ <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/prune-after-obslog.log obslog -r "prune" --hidden + x <span style="color:olive;">324b72ebbb21</span> <span style="color:blue;">(9)</span> Commit to prune + pruned by <span style="color:green;">test</span> <span style="color:teal;">(Thu Jan 01 00:00:00 1970 +0000)</span> + + $ graph $TESTDIR/graphs/prune-after-hidden.dot -r '::prune' -T "{shortest(node, 8)}" --hidden --public=yes + Wrote */graphs/prune-after-hidden.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 9 [fillcolor="#DFDFFF", + fixedsize=true, + group=prune_extinct, + height=1, + label="324b72eb", + pin=true, + pos="2,9!", + shape=circle, + style="dotted, filled", + width=1]; + 0 -> 9 [penwidth=2.0]; + } + +Histedit +-------- + + $ hg up histedit + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/histedit-before-log.log log -G -r "::histedit" + @ <span style="color:olive;">changeset: 16:1b1e58a9ed27</span> + | branch: histedit + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:37:15 2017 +0100 + | summary: Add test for myfeature + | + o <span style="color:olive;">changeset: 15:23eb6f9e4c51</span> + | branch: histedit + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:35:15 2017 +0100 + | summary: Add code for myfeature + | + o <span style="color:olive;">changeset: 14:d102c718e607</span> + | branch: histedit + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:33:15 2017 +0100 + | summary: First commit on histedit branch + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + $ graph $TESTDIR/graphs/histedit-before.dot -r "::histedit" -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/histedit-before.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 14 [fillcolor="#7F7FFF", + fixedsize=true, + group=histedit, + height=1, + label=d102c718, + pin=true, + pos="2,14!", + shape=circle, + style=filled, + width=1]; + 0 -> 14 [penwidth=2.0]; + 15 [fillcolor="#7F7FFF", + fixedsize=true, + group=histedit, + height=1, + label="23eb6f9e", + pin=true, + pos="2,15!", + shape=circle, + style=filled, + width=1]; + 14 -> 15 [penwidth=2.0]; + 16 [fillcolor="#7F7FFF", + fixedsize=true, + group=histedit, + height=1, + label="1b1e58a9", + pin=true, + pos="2,16!", + shape=circle, + style=filled, + width=1]; + 15 -> 16 [penwidth=2.0]; + } + + $ HGEDITOR=cat html_output $TESTDIR/output/histedit-no-edit.log histedit -r ".~1" + pick 23eb6f9e4c51 15 Add code for myfeature + pick 1b1e58a9ed27 16 Add test for myfeature + + # Edit history between 23eb6f9e4c51 and 1b1e58a9ed27 + # + # Commits are listed from least to most recent + # + # You can reorder changesets by reordering the lines + # + # Commands: + # + # e, edit = use commit, but stop for amending + # m, mess = edit commit message without changing commit content + # p, pick = use commit + # b, base = checkout changeset and apply further changesets from there + # d, drop = remove commit from history + # f, fold = use commit, but combine it with the one above + # r, roll = like fold, but discard this commit's description and date + # + +Format the commands the best way we can + + $ HGEDITOR=cat hg histedit -r ".~1" | head -n 2 | tail -n 1 > commands + $ HGEDITOR=cat hg histedit -r ".~1" | head -n 1 >> commands + + $ html_raw_output $TESTDIR/output/histedit-commands.log cat commands + pick 1b1e58a9ed27 16 Add test for myfeature + pick 23eb6f9e4c51 15 Add code for myfeature + + $ HGEDITOR=cat html_output $TESTDIR/output/histedit.log histedit -r ".~1" --commands commands + + $ html_output $TESTDIR/output/histedit-after-log.log log -G -r ""::histedit"" + @ <span style="color:olive;">changeset: 30:27cb89067c43</span> + | branch: histedit + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:35:15 2017 +0100 + | summary: Add code for myfeature + | + o <span style="color:olive;">changeset: 29:a2082e406c4f</span> + | branch: histedit + | parent: 14:d102c718e607 + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:37:15 2017 +0100 + | summary: Add test for myfeature + | + o <span style="color:olive;">changeset: 14:d102c718e607</span> + | branch: histedit + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:33:15 2017 +0100 + | summary: First commit on histedit branch + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ html_output $TESTDIR/output/histedit-after-log-hidden.log log -G -r "::branch(histedit)" --hidden + @ <span style="color:olive;">changeset: 30:27cb89067c43</span> + | branch: histedit + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:35:15 2017 +0100 + | summary: Add code for myfeature + | + o <span style="color:olive;">changeset: 29:a2082e406c4f</span> + | branch: histedit + | parent: 14:d102c718e607 + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:37:15 2017 +0100 + | summary: Add test for myfeature + | + | x <span style="color:olive;">changeset: 16:1b1e58a9ed27</span> + | | branch: histedit + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Sat Dec 09 17:37:15 2017 +0100 + | | obsolete: rebased using histedit as 29:a2082e406c4f + | | summary: Add test for myfeature + | | + | x <span style="color:olive;">changeset: 15:23eb6f9e4c51</span> + |/ branch: histedit + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:35:15 2017 +0100 + | obsolete: rebased using histedit as 30:27cb89067c43 + | summary: Add code for myfeature + | + o <span style="color:olive;">changeset: 14:d102c718e607</span> + | branch: histedit + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Sat Dec 09 17:33:15 2017 +0100 + | summary: First commit on histedit branch + | + o <span style="color:olive;">changeset: 0:d2eb2ac6a5bd</span> + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + $ graph $TESTDIR/graphs/histedit-after-hidden.dot -r "::branch(histedit)" -T "{shortest(node, 8)}" --public=yes --hidden + Wrote */graphs/histedit-after-hidden.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=d2eb2ac6, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 14 [fillcolor="#7F7FFF", + fixedsize=true, + group=histedit, + height=1, + label=d102c718, + pin=true, + pos="2,14!", + shape=circle, + style=filled, + width=1]; + 0 -> 14 [penwidth=2.0]; + 15 [fillcolor="#DFDFFF", + fixedsize=true, + group=histedit_extinct, + height=1, + label="23eb6f9e", + pin=true, + pos="3,15!", + shape=circle, + style="dotted, filled", + width=1]; + 14 -> 15 [penwidth=2.0]; + 29 [fillcolor="#7F7FFF", + fixedsize=true, + group=histedit, + height=1, + label=a2082e40, + pin=true, + pos="2,29!", + shape=circle, + style=filled, + width=1]; + 14 -> 29 [penwidth=2.0]; + 30 [fillcolor="#7F7FFF", + fixedsize=true, + group=histedit, + height=1, + label="27cb8906", + pin=true, + pos="2,30!", + shape=circle, + style=filled, + width=1]; + 15 -> 30 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 16 [fillcolor="#DFDFFF", + fixedsize=true, + group=histedit_extinct, + height=1, + label="1b1e58a9", + pin=true, + pos="3,16!", + shape=circle, + style="dotted, filled", + width=1]; + 15 -> 16 [penwidth=2.0]; + 16 -> 29 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 29 -> 30 [penwidth=2.0]; + } + +Stack +----- + + $ hg update typo + 1 files updated, 0 files merged, 2 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/stack-typo.log stack + ### target: typo (branch) + <span style="color:teal;">b1</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Fix bug</span><span style="color:teal;font-weight:bold;"> (current)</span> + b0^ ROOT (base) + + $ hg update build/linuxsupport-v2 + 4 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/stack-rebase.log stack + ### target: build/linuxsupport-v2 (branch) + <span style="color:teal;">b3</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Third commit on build/linuxsupport-v2</span><span style="color:teal;font-weight:bold;"> (current)</span> + <span style="color:olive;">b2</span><span style="color:green;">:</span> Second commit on build/linuxsupport-v2. + <span style="color:olive;">b1</span><span style="color:green;">:</span> First commit on build/linuxsupport-v2 + b0^ New commit on build/v2 (base) + + $ html_output $TESTDIR/output/stack-rebase-prev-from-b3.log prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [<span style="color:blue;">19</span>] Second commit on build/linuxsupport-v2. + + $ html_output $TESTDIR/output/stack-rebase-stack-b2.log stack + ### target: build/linuxsupport-v2 (branch) + <span style="color:olive;">b3</span><span style="color:green;">:</span> Third commit on build/linuxsupport-v2 + <span style="color:teal;">b2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Second commit on build/linuxsupport-v2.</span><span style="color:teal;font-weight:bold;"> (current)</span> + <span style="color:olive;">b1</span><span style="color:green;">:</span> First commit on build/linuxsupport-v2 + b0^ New commit on build/v2 (base) + + $ html_output $TESTDIR/output/stack-rebase-next-from-b2.log next + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + [<span style="color:blue;">20</span>] Third commit on build/linuxsupport-v2 + + $ html_output $TESTDIR/output/stack-rebase-export-b1.log export -r b1 + # HG changeset patch + # User Boris Feld <boris.feld@octobus.net> + # Date 1512661592 -3600 + # Thu Dec 07 16:46:32 2017 +0100 + # Branch build/linuxsupport-v2 + # Node ID 7b62ce2c283e6fa23af1811efea529c30620196a + # Parent 0e694460372ee8e9ca759c90f05a31f11eee34ac + First commit on build/linuxsupport-v2 + + $ html_output $TESTDIR/output/stack-rebase-update-b2.log update -r b2 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + + $ html_output $TESTDIR/output/stack-rebase-stack-b2.log stack + ### target: build/linuxsupport-v2 (branch) + <span style="color:olive;">b3</span><span style="color:green;">:</span> Third commit on build/linuxsupport-v2 + <span style="color:teal;">b2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Second commit on build/linuxsupport-v2.</span><span style="color:teal;font-weight:bold;"> (current)</span> + <span style="color:olive;">b1</span><span style="color:green;">:</span> First commit on build/linuxsupport-v2 + b0^ New commit on build/v2 (base) + + +Edit mid-stack +-------------- + + $ html_output $TESTDIR/output/edit-mid-stack.log amend -m "Second commit on build/linuxsupport-v2" + 1 new orphan changesets + + $ html_output $TESTDIR/output/edit-mid-stack-after-stack.log stack + ### target: build/linuxsupport-v2 (branch) + <span style="color:olive;">b3</span><span style="color:red;">$</span> Third commit on build/linuxsupport-v2<span style="color:red;"> (unstable)</span> + <span style="color:teal;">b2</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Second commit on build/linuxsupport-v2</span><span style="color:teal;font-weight:bold;"> (current)</span> + <span style="color:olive;">b1</span><span style="color:green;">:</span> First commit on build/linuxsupport-v2 + b0^ New commit on build/v2 (base) + + $ html_output $TESTDIR/output/edit-mid-stack-after-log.log log -r "branch(build/linuxsupport-v2)" -G + @ <span style="color:olive;">changeset: 31:5c069dd03e05</span> + | branch: build/linuxsupport-v2 + | tag: tip + | parent: 18:7b62ce2c283e + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | summary: Second commit on build/linuxsupport-v2 + | + | o <span style="color:olive;">changeset: 20:3d2c8a2356a2</span> + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:21:02 2017 +0100 + | | instability: orphan + | | summary: Third commit on build/linuxsupport-v2 + | | + | x <span style="color:olive;">changeset: 19:4686378320d7</span> + |/ branch: build/linuxsupport-v2 + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | obsolete: reworded using amend as 31:5c069dd03e05 + | summary: Second commit on build/linuxsupport-v2. + | + o <span style="color:olive;">changeset: 18:7b62ce2c283e</span> + | branch: build/linuxsupport-v2 + ~ parent: 6:0e694460372e + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 16:46:32 2017 +0100 + summary: First commit on build/linuxsupport-v2 + + + $ graph $TESTDIR/graphs/edit-mid-stack-after.dot -r "branch(build/linuxsupport-v2)" -T "{shortest(node, 8)}" --public=yes + Wrote */graphs/edit-mid-stack-after.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="7b62ce2c", + pin=true, + pos="1,18!", + shape=circle, + style=filled, + width=1]; + 19 [fillcolor="#DFDFFF", + fixedsize=true, + group="build/linuxsupport-v2_alt", + height=1, + label=46863783, + pin=true, + pos="2,19!", + shape=circle, + style="dotted, filled", + width=1]; + 18 -> 19 [penwidth=2.0]; + 31 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="5c069dd0", + pin=true, + pos="1,31!", + shape=circle, + style=filled, + width=1]; + 18 -> 31 [penwidth=2.0]; + 19 -> 31 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 20 [fillcolor="#FF4F4F", + fixedsize=true, + group="build/linuxsupport-v2_alt", + height=1, + label="3d2c8a23", + pin=true, + pos="2,20!", + shape=circle, + style=filled, + width=1]; + 19 -> 20 [penwidth=2.0]; + } + +Basic troubles + stabilization +------------------------------ + + $ cp -R $TESTTMP/evolve_training_repo $TESTDIR/base-repos/edit-mid-stack/ + + $ html_output $TESTDIR/output/basic-stabilize-before-log-obsolete.log log -r "branch(build/linuxsupport-v2)" -G -T "{node|short}: {obsolete}\n" + @ 5c069dd03e05: + | + | o 3d2c8a2356a2: + | | + | x 4686378320d7: obsolete + |/ + o 7b62ce2c283e: + | + ~ + + $ html_output $TESTDIR/output/basic-stabilize-before-log-instabilities.log log -r "branch(build/linuxsupport-v2)" -G -T "{node|short}: {instabilities}\n" + @ 5c069dd03e05: + | + | o 3d2c8a2356a2: orphan + | | + | x 4686378320d7: + |/ + o 7b62ce2c283e: + | + ~ + + $ html_output $TESTDIR/output/basic-stabilize-before-evolve-list.log evolve --list + 3d2c8a2356a2: Third commit on build/linuxsupport-v2 + unstable: 4686378320d7 (obsolete parent) + + $ html_output $TESTDIR/output/basic-stabilize-next-evolve.log next --evolve + move:[<span style="color:blue;">20</span>] Third commit on build/linuxsupport-v2 + atop:[<span style="color:blue;">31</span>] Second commit on build/linuxsupport-v2 + working directory now at <span style="color:olive;">52e790f9d4c3</span> + + $ html_output $TESTDIR/output/basic-stabilize-after-stack.log stack + ### target: build/linuxsupport-v2 (branch) + <span style="color:teal;">b3</span><span style="color:teal;font-weight:bold;">@</span> <span style="color:teal;">Third commit on build/linuxsupport-v2</span><span style="color:teal;font-weight:bold;"> (current)</span> + <span style="color:olive;">b2</span><span style="color:green;">:</span> Second commit on build/linuxsupport-v2 + <span style="color:olive;">b1</span><span style="color:green;">:</span> First commit on build/linuxsupport-v2 + b0^ New commit on build/v2 (base) + + $ graph $TESTDIR/graphs/basic-stabilize-after-stack.dot -T "{shortest(node, 8)}" -r "(::. + ::precursors(.)) and branch(build/linuxsupport-v2)" --hidden --public=yes + Wrote */graphs/basic-stabilize-after-stack.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="7b62ce2c", + pin=true, + pos="1,18!", + shape=circle, + style=filled, + width=1]; + 31 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="5c069dd0", + pin=true, + pos="1,31!", + shape=circle, + style=filled, + width=1]; + 18 -> 31 [penwidth=2.0]; + 19 [fillcolor="#DFDFFF", + fixedsize=true, + group="build/linuxsupport-v2_extinct", + height=1, + label=46863783, + pin=true, + pos="2,19!", + shape=circle, + style="dotted, filled", + width=1]; + 18 -> 19 [penwidth=2.0]; + 32 [fillcolor="#7F7FFF", + fixedsize=true, + group="build/linuxsupport-v2", + height=1, + label="52e790f9", + pin=true, + pos="1,32!", + shape=circle, + style=filled, + width=1]; + 31 -> 32 [penwidth=2.0]; + 19 -> 31 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 20 [fillcolor="#DFDFFF", + fixedsize=true, + group="build/linuxsupport-v2_extinct", + height=1, + label="3d2c8a23", + pin=true, + pos="2,20!", + shape=circle, + style="dotted, filled", + width=1]; + 19 -> 20 [penwidth=2.0]; + 20 -> 32 [arrowtail=dot, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + } +Basic exchange +-------------- + + $ html_output $TESTDIR/output/basic-exchange-clone.log clone . ../evolve_training_repo_server/ + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ cd ../evolve_training_repo_server + + $ hg log -G + o changeset: 32:52e790f9d4c3 + | branch: build/linuxsupport-v2 + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:21:02 2017 +0100 + | summary: Third commit on build/linuxsupport-v2 + | + o changeset: 31:5c069dd03e05 + | branch: build/linuxsupport-v2 + | parent: 18:7b62ce2c283e + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | summary: Second commit on build/linuxsupport-v2 + | + | o changeset: 30:27cb89067c43 + | | branch: histedit + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Sat Dec 09 17:35:15 2017 +0100 + | | summary: Add code for myfeature + | | + | o changeset: 29:a2082e406c4f + | | branch: histedit + | | parent: 14:d102c718e607 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Sat Dec 09 17:37:15 2017 +0100 + | | summary: Add test for myfeature + | | + | | o changeset: 28:1b7281b1e052 + | | | branch: split + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: To be splitted + | | | + | | o changeset: 27:6fb7bfb44ffe + | | | branch: split + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: To be splitted + | | | + | | o changeset: 26:59f0ddc4bd4b + | | | branch: split + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: To be splitted + | | | + | | | o changeset: 25:dab6ed4b3c75 + | | |/ branch: fold + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: add a test + | | | + | | | o changeset: 24:76ace846a3f9 + | | | | branch: amend-extract + | | | | parent: 7:4ae0d1de7a58 + | | | | user: Good User + | | | | date: Fri Dec 08 15:28:46 2017 +0100 + | | | | summary: Commit to be extracted + | | | | + o | | | changeset: 18:7b62ce2c283e + | | | | branch: build/linuxsupport-v2 + | | | | parent: 6:0e694460372e + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Thu Dec 07 16:46:32 2017 +0100 + | | | | summary: First commit on build/linuxsupport-v2 + | | | | + | | +---o changeset: 17:708369dc1bfe + | | | | branch: typo + | | | | parent: 0:d2eb2ac6a5bd + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Thu Dec 07 11:26:53 2017 +0100 + | | | | summary: Fix bug + | | | | + | o | | changeset: 14:d102c718e607 + | |/ / branch: histedit + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Sat Dec 09 17:33:15 2017 +0100 + | | | summary: First commit on histedit branch + | | | + | | o changeset: 7:4ae0d1de7a58 + | |/ branch: amend-extract + | | parent: 0:d2eb2ac6a5bd + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Fri Dec 08 15:04:09 2017 +0100 + | | summary: Base file + | | + o | changeset: 6:0e694460372e + | | branch: build/v2 + | | parent: 2:f3bd0ab4ee87 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:22:16 2017 +0100 + | | summary: New commit on build/v2 + | | + o | changeset: 2:f3bd0ab4ee87 + |/ branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + @ changeset: 0:d2eb2ac6a5bd + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + + + +FINAL STAY AT THE END + + $ cd $TESTTMP/evolve_training_repo + + $ hg log -G --hidden + @ changeset: 32:52e790f9d4c3 + | branch: build/linuxsupport-v2 + | tag: tip + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:21:02 2017 +0100 + | summary: Third commit on build/linuxsupport-v2 + | + o changeset: 31:5c069dd03e05 + | branch: build/linuxsupport-v2 + | parent: 18:7b62ce2c283e + | user: Boris Feld <boris.feld@octobus.net> + | date: Mon Dec 11 11:20:24 2017 +0100 + | summary: Second commit on build/linuxsupport-v2 + | + | o changeset: 30:27cb89067c43 + | | branch: histedit + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Sat Dec 09 17:35:15 2017 +0100 + | | summary: Add code for myfeature + | | + | o changeset: 29:a2082e406c4f + | | branch: histedit + | | parent: 14:d102c718e607 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Sat Dec 09 17:37:15 2017 +0100 + | | summary: Add test for myfeature + | | + | | o changeset: 28:1b7281b1e052 + | | | branch: split + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: To be splitted + | | | + | | o changeset: 27:6fb7bfb44ffe + | | | branch: split + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: To be splitted + | | | + | | o changeset: 26:59f0ddc4bd4b + | | | branch: split + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: To be splitted + | | | + | | | o changeset: 25:dab6ed4b3c75 + | | |/ branch: fold + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Thu Jan 01 00:00:00 1970 +0000 + | | | summary: add a test + | | | + | | | o changeset: 24:76ace846a3f9 + | | | | branch: amend-extract + | | | | parent: 7:4ae0d1de7a58 + | | | | user: Good User + | | | | date: Fri Dec 08 15:28:46 2017 +0100 + | | | | summary: Commit to be extracted + | | | | + | | | | x changeset: 23:008eb7da195a + | | | |/ branch: amend-extract + | | | | parent: 7:4ae0d1de7a58 + | | | | user: Good User + | | | | date: Fri Dec 08 15:28:46 2017 +0100 + | | | | obsolete: pruned + | | | | summary: temporary commit for uncommiting 1e04751ef00a + | | | | + | | | | x changeset: 22:1e04751ef00a + | | | |/ branch: amend-extract + | | | | parent: 7:4ae0d1de7a58 + | | | | user: Good User + | | | | date: Fri Dec 08 15:28:46 2017 +0100 + | | | | obsolete: amended as 24:76ace846a3f9 + | | | | summary: Commit to be extracted + | | | | + | | | | x changeset: 21:5935c1c3ad24 + | | | |/ branch: amend-extract + | | | | parent: 7:4ae0d1de7a58 + | | | | user: Good User + | | | | date: Fri Dec 08 15:28:46 2017 +0100 + | | | | obsolete: amended as 22:1e04751ef00a + | | | | summary: Commit to be extracted + | | | | + | | | | x changeset: 20:3d2c8a2356a2 + | | | | | branch: build/linuxsupport-v2 + | | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | | date: Mon Dec 11 11:21:02 2017 +0100 + | | | | | obsolete: rebased as 32:52e790f9d4c3 + | | | | | summary: Third commit on build/linuxsupport-v2 + | | | | | + +-------x changeset: 19:4686378320d7 + | | | | branch: build/linuxsupport-v2 + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Mon Dec 11 11:20:24 2017 +0100 + | | | | obsolete: reworded using amend as 31:5c069dd03e05 + | | | | summary: Second commit on build/linuxsupport-v2. + | | | | + o | | | changeset: 18:7b62ce2c283e + | | | | branch: build/linuxsupport-v2 + | | | | parent: 6:0e694460372e + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Thu Dec 07 16:46:32 2017 +0100 + | | | | summary: First commit on build/linuxsupport-v2 + | | | | + | | +---o changeset: 17:708369dc1bfe + | | | | branch: typo + | | | | parent: 0:d2eb2ac6a5bd + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Thu Dec 07 11:26:53 2017 +0100 + | | | | summary: Fix bug + | | | | + | | | | x changeset: 16:1b1e58a9ed27 + | | | | | branch: histedit + | | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | | date: Sat Dec 09 17:37:15 2017 +0100 + | | | | | obsolete: rebased using histedit as 29:a2082e406c4f + | | | | | summary: Add test for myfeature + | | | | | + | +-----x changeset: 15:23eb6f9e4c51 + | | | | branch: histedit + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Sat Dec 09 17:35:15 2017 +0100 + | | | | obsolete: rebased using histedit as 30:27cb89067c43 + | | | | summary: Add code for myfeature + | | | | + | o | | changeset: 14:d102c718e607 + | |/ / branch: histedit + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Sat Dec 09 17:33:15 2017 +0100 + | | | summary: First commit on histedit branch + | | | + | +---x changeset: 13:5d5029b9daed + | | | branch: split + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Fri Dec 08 17:33:15 2017 +0100 + | | | obsolete: split as 26:59f0ddc4bd4b, 27:6fb7bfb44ffe, 28:1b7281b1e052 + | | | summary: To be splitted + | | | + | | | x changeset: 12:966df9f031c1 + | | | | branch: fold + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Fri Dec 08 16:50:38 2017 +0100 + | | | | obsolete: rewritten as 25:dab6ed4b3c75 + | | | | summary: Really fix the test + | | | | + | | | x changeset: 11:b316dc02bddc + | | | | branch: fold + | | | | user: Boris Feld <boris.feld@octobus.net> + | | | | date: Fri Dec 08 16:50:17 2017 +0100 + | | | | obsolete: rewritten as 25:dab6ed4b3c75 + | | | | summary: Fix the test + | | | | + | +---x changeset: 10:03174536bb2a + | | | branch: fold + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Fri Dec 08 16:49:45 2017 +0100 + | | | obsolete: rewritten as 25:dab6ed4b3c75 + | | | summary: add a test + | | | + | +---x changeset: 9:324b72ebbb21 + | | | branch: prune + | | | parent: 0:d2eb2ac6a5bd + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Fri Dec 08 16:12:23 2017 +0100 + | | | obsolete: pruned + | | | summary: Commit to prune + | | | + | | | x changeset: 8:e288d12d5e96 + | | |/ branch: amend-extract + | | | user: Bad User + | | | date: Fri Dec 08 15:28:46 2017 +0100 + | | | obsolete: reauthored using amend as 21:5935c1c3ad24 + | | | summary: Commit to be extracted + | | | + | | o changeset: 7:4ae0d1de7a58 + | |/ branch: amend-extract + | | parent: 0:d2eb2ac6a5bd + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Fri Dec 08 15:04:09 2017 +0100 + | | summary: Base file + | | + o | changeset: 6:0e694460372e + | | branch: build/v2 + | | parent: 2:f3bd0ab4ee87 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Mon Dec 11 11:22:16 2017 +0100 + | | summary: New commit on build/v2 + | | + | | x changeset: 5:39e9774ab30b + | | | branch: build/linuxsupport-v2 + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Mon Dec 11 11:21:02 2017 +0100 + | | | obsolete: rebased using rebase as 20:3d2c8a2356a2 + | | | summary: Third commit on build/linuxsupport-v2 + | | | + | | x changeset: 4:5ad93176b041 + | | | branch: build/linuxsupport-v2 + | | | user: Boris Feld <boris.feld@octobus.net> + | | | date: Mon Dec 11 11:20:24 2017 +0100 + | | | obsolete: rebased using rebase as 19:4686378320d7 + | | | summary: Second commit on build/linuxsupport-v2. + | | | + +---x changeset: 3:424916b62f4c + | | branch: build/linuxsupport-v2 + | | user: Boris Feld <boris.feld@octobus.net> + | | date: Thu Dec 07 16:46:32 2017 +0100 + | | obsolete: rebased using rebase as 18:7b62ce2c283e + | | summary: First commit on build/linuxsupport-v2 + | | + o | changeset: 2:f3bd0ab4ee87 + |/ branch: build/v2 + | parent: 0:d2eb2ac6a5bd + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 16:45:07 2017 +0100 + | summary: First commit on build/v2 + | + | x changeset: 1:5d48a444aba7 + |/ branch: typo + | user: Boris Feld <boris.feld@octobus.net> + | date: Thu Dec 07 11:26:53 2017 +0100 + | obsolete: reworded using amend as 17:708369dc1bfe + | summary: Fx bug + | + o changeset: 0:d2eb2ac6a5bd + user: Boris Feld <boris.feld@octobus.net> + date: Thu Dec 07 11:26:05 2017 +0100 + summary: ROOT + +Phases graph repository +======================= + + $ hg init $TESTTMP/phases + $ cd $TESTTMP/phases + + $ hg commit -m "Public" --config ui.allowemptycommit=true + $ hg phase -p . + + $ hg commit -m "Draft" --config ui.allowemptycommit=true + + $ hg commit -s -m "Secret" --config ui.allowemptycommit=true + + $ hg log -G -T "{rev} {phase}\n" + @ 2 secret + | + o 1 draft + | + o 0 public + + $ graph $TESTDIR/graphs/phases.dot -r "all()" -T "{desc}" + Wrote */graphs/phases.dot (glob) + .. graphviz:: + + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=Public, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 1 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=Draft, + pin=true, + pos="1,1!", + shape=pentagon, + style=filled, + width=1]; + 0 -> 1 [penwidth=2.0]; + 2 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=Secret, + pin=true, + pos="1,2!", + shape=square, + style=filled, + width=1]; + 1 -> 2 [penwidth=2.0]; + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/arguments_printer.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,22 @@ +import sys + +formatted_args = [] + +UNSAFE_CHARACTERS = [" ", "!", "\"", "#", "$", "&", "'", "(", ")", "*", ",", ";", "<", ">", "?", "[", "\\", "]", "^", "`", "{", "|", "}", ":", "~", "/"] + + +def find_unsafe(arg): + for unsafe in UNSAFE_CHARACTERS: + if unsafe in arg: + return True + + return False + + +for arg in sys.argv[1:]: + if find_unsafe(arg): + formatted_args.append('"%s"' % arg) + else: + formatted_args.append(arg) + +print("$ " + " ".join(formatted_args))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/common.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,40 @@ +#!/bin/bash +. $TESTDIR/testlib/pythonpath.sh + +mkcommit() { + echo "$1" > "$1" + hg add "$1" + hg ci -m "$1" +} + +getid() { + hg log --hidden --template '{node}\n' --rev "$1" +} + +cat >> $HGRCPATH <<EOF +[alias] +debugobsolete=debugobsolete -d '0 0' +EOF + +html_output() { + filepath="$1" + touch "$filepath" + shift + + python $TESTDIR/testlib/arguments_printer.py 'hg' "$@" > "$filepath" + hg "$@" --color=always 2>&1 | aha -n | tee -a "$filepath" +} + +html_raw_output() { + filepath="$1" + touch "$filepath" + shift + + # python $TESTDIR/testlib/arguments_printer.py "$@" > "$filepath" + echo "" > "$filepath" + "$@" | tee -a "$filepath" +} + +graph() { + hg docgraph --rankdir LR --arrowhead=true --obsarrowhead=true --sphinx-directive --dot-output "$@" +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/docgraph_setup.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,6 @@ +. $TESTDIR/testlib/pythonpath.sh + +cat >> $HGRCPATH << EOF +[extensions] +docgraph= +EOF
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/exchange-obsmarker-util.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,141 @@ +#!/bin/sh +# setup config and various utility to test obsolescence marker exchanges tests + +cat >> $HGRCPATH <<EOF +[web] +# We test http pull and push, drop authentication requirement +push_ssl = false +allow_push = * + +[ui] +# simpler log output +logtemplate ="{node|short} ({phase}): {desc}\n" + +[phases] +# non publishing server +publish=False + +[experimental] +# reduce output changes +bundle2-output-capture=True +# enable evolution +evolution=all +evolution.effect-flags = yes + +[extensions] +# we need to strip some changeset for some test cases +hgext.strip= + +[alias] +# fix date used to create obsolete markers. +debugobsolete=debugobsolete -d '0 0' + +[extensions] +hgext.strip= +EOF +echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + +mkcommit() { + echo "$1" > "$1" + hg add "$1" + hg ci -m "$1" +} +getid() { + hg log --hidden --template '{node}\n' --rev "$1" +} + +setuprepos() { + echo creating test repo for test case $1 + mkdir $1 + cd $1 + echo - pulldest + hg init pushdest + cd pushdest + mkcommit O + hg phase --public . + cd .. + echo - main + hg clone -q pushdest main + echo - pushdest + hg clone -q main pulldest + echo 'cd into `main` and proceed with env setup' +} + +inspect_obsmarkers (){ + # This exist as its own function to help the evolve extension reuse the tests as is. + # The evolve extensions version will includes more advances query (eg: + # related to obsmarkers discovery) to this. + echo 'obsstore content' + echo '================' + hg debugobsolete + echo 'obshashtree' + echo '===========' + hg debugobsrelsethashtree + echo 'obshashrange' + echo '============' + hg debugobshashrange --subranges --rev 'head()' +} + +dotest() { + # dotest TESTNAME [TARGETNODE] [PUSHFLAGS+] + # + # test exchange for the given test case. + # + # This function performs push and pull in all directions through all + # protocols and display the resulting obsolescence markers on all sides. + + testcase=$1 + shift + target="$1" + if [ $# -gt 0 ]; then + shift + fi + targetnode="" + desccall="" + cd $testcase + echo "## Running testcase $testcase" + if [ -n "$target" ]; then + desccall="desc("\'"$target"\'")" + targetnode="`hg -R main id -qr \"$desccall\"`" + echo "# testing echange of \"$target\" ($targetnode)" + fi + echo "## initial state" + echo "# obstore: main" + hg -R main debugobsolete | sort + echo "# obstore: pushdest" + hg -R pushdest debugobsolete | sort + echo "# obstore: pulldest" + hg -R pulldest debugobsolete | sort + + if [ -n "$target" ]; then + echo "## pushing \"$target\"" from main to pushdest + hg -R main push -r "$desccall" $@ pushdest + else + echo "## pushing from main to pushdest" + hg -R main push pushdest $@ + fi + echo "## post push state" + echo "# obstore: main" + hg -R main debugobsolete | sort + echo "# obstore: pushdest" + hg -R pushdest debugobsolete | sort + echo "# obstore: pulldest" + hg -R pulldest debugobsolete | sort + if [ -n "$target" ]; then + echo "## pulling \"$targetnode\"" from main into pulldest + hg -R pulldest pull -r $targetnode $@ main + else + echo "## pulling from main into pulldest" + hg -R pulldest pull main $@ + fi + echo "## post pull state" + echo "# obstore: main" + hg -R main debugobsolete | sort + echo "# obstore: pushdest" + hg -R pushdest debugobsolete | sort + echo "# obstore: pulldest" + hg -R pulldest debugobsolete | sort + + cd .. + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/push-checkheads-util.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,29 @@ +# setup config and various utility to test new heads checks on push + +. $TESTDIR/testlib/common.sh + +cat >> $HGRCPATH <<EOF +[ui] +# simpler log output +logtemplate ="{node|short} ({phase}): {desc}\n" + +[phases] +# non publishing server +publish=False + +[extensions] +# we need to strip some changeset for some test cases +strip= +evolve= +EOF + +setuprepos() { + echo creating basic server and client repo + hg init server + cd server + mkcommit root + hg phase --public . + mkcommit A0 + cd .. + hg clone server client +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/pythonpath.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,9 @@ +# utility to setup pythonpath to point into the tested repository + +export SRCDIR=`dirname $TESTDIR` +if [ -n "$PYTHONPATH" ]; then + export HGTEST_ORIG_PYTHONPATH=$PYTHONPATH + export PYTHONPATH=$SRCDIR:$PYTHONPATH +else + export PYTHONPATH=$SRCDIR +fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/testlib/topic_setup.sh Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,16 @@ +#!/bin/sh +. $TESTDIR/testlib/pythonpath.sh + +# This file holds logic that is used in many tests. +# It can be called in a test like this: +# $ . "$TESTDIR/testlib/topic_setup.sh" + +# Enable obsolete markers and enable extensions +cat >> $HGRCPATH << EOF +[experimental] +evolution=createmarkers,exchange + +[extensions] +rebase= +topic= +EOF
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/uikit.css Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,9854 @@ +html { + font: normal 14px / 20px "Helvetica Neue", Helvetica, Arial, sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + background: #fff; + color: #444; + background-image: -webkit-radial-gradient(100% 100%, center, #fff, #fff); + background-image: radial-gradient(100% 100% at center, #fff, #fff) +} + +body { + margin: 0 +} + +a { + background: transparent +} + +a:active, +a:hover { + outline: 0 +} + +a, +.uk-link { + color: #07d; + text-decoration: none; + cursor: pointer +} + +a:hover, +.uk-link:hover { + color: #059; + text-decoration: underline +} + +abbr[title] { + border-bottom: 1px dotted +} + +b, +strong { + font-weight: bold +} + +:not(pre)>code, +:not(pre)>kbd, +:not(pre)>samp { + font-size: 12px; + font-family: Consolas, monospace, serif; + color: #666; + white-space: nowrap; + padding: 0 4px; + border: 1px solid #ddd; + border-radius: 3px; + background: #fafafa +} + +em { + color: #666 +} + +ins { + background: #ffa; + color: #444; + text-decoration: none +} + +mark { + background: #ffa; + color: #444 +} + +q { + font-style: italic +} + +small { + font-size: 80% +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline +} + +sup { + top: -0.5em +} + +sub { + bottom: -0.25em +} + +audio, +canvas, +iframe, +img, +svg, +video { + vertical-align: middle +} + +img { + max-width: 100%; + height: auto; + box-sizing: border-box; + border: 0 +} + +.uk-img-preserve, +.uk-img-preserve img { + max-width: none +} + +svg:not(:root) { + overflow: hidden +} + +blockquote, +figure { + margin: 0 +} + +p, +ul, +ol, +dl, +blockquote, +pre, +address, +fieldset, +figure { + margin: 0 0 15px 0 +} + +*+p, +*+ul, +*+ol, +*+dl, +*+blockquote, +*+pre, +*+address, +*+fieldset, +*+figure { + margin-top: 15px +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0 0 15px 0; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + color: #444; + text-transform: none +} + +*+h1, +*+h2, +*+h3, +*+h4, +*+h5, +*+h6 { + margin-top: 25px +} + +h1, +.uk-h1 { + font-size: 36px; + line-height: 42px +} + +h2, +.uk-h2 { + font-size: 24px; + line-height: 30px +} + +h3, +.uk-h3 { + font-size: 18px; + line-height: 24px +} + +h4, +.uk-h4 { + font-size: 16px; + line-height: 22px +} + +h5, +.uk-h5 { + font-size: 14px; + line-height: 20px +} + +h6, +.uk-h6 { + font-size: 12px; + line-height: 18px +} + +ul, +ol { + padding-left: 30px +} + +ul>li>ul, +ul>li>ol, +ol>li>ol, +ol>li>ul { + margin: 0 +} + +dt { + font-weight: bold +} + +dd { + margin-left: 0 +} + +hr { + box-sizing: content-box; + height: 0; + margin: 15px 0; + border: 0; + border-top: 1px solid #ddd +} + +address { + font-style: normal +} + +blockquote { + padding-left: 15px; + border-left: 5px solid #ddd; + font-size: 16px; + line-height: 22px; + font-style: italic +} + +pre { + padding: 10px; + background: #fafafa; + font: 12px / 18px Consolas, monospace, serif; + color: #444; + -moz-tab-size: 4; + tab-size: 4; + overflow: auto; + border: 1px solid #ddd; + border-radius: 3px +} + +::-moz-selection { + background: #39f; + color: #fff; + text-shadow: none +} + +::selection { + background: #39f; + color: #fff; + text-shadow: none +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +main, +nav, +section, +summary { + display: block +} + +progress { + vertical-align: baseline +} + +audio:not([controls]) { + display: none +} + +[hidden], +template { + display: none +} + +iframe { + border: 0 +} + +@media screen and (max-width:400px) { + @-ms-viewport { + width: device-width + } +} + +.uk-grid { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin: 0; + padding: 0; + list-style: none +} + +.uk-grid:before, +.uk-grid:after { + content: ""; + display: block; + overflow: hidden +} + +.uk-grid:after { + clear: both +} + +.uk-grid>* { + -ms-flex: none; + -webkit-flex: none; + flex: none; + margin: 0; + float: left +} + +.uk-grid>*>:last-child { + margin-bottom: 0 +} + +.uk-grid { + margin-left: -25px +} + +.uk-grid>* { + padding-left: 25px +} + +.uk-grid+.uk-grid, +.uk-grid-margin, +.uk-grid>*>.uk-panel+.uk-panel { + margin-top: 25px +} + +@media (min-width:1220px) { + .uk-grid { + margin-left: -35px + } + .uk-grid>* { + padding-left: 35px + } + .uk-grid+.uk-grid, + .uk-grid-margin, + .uk-grid>*>.uk-panel+.uk-panel { + margin-top: 35px + } +} + +.uk-grid-collapse { + margin-left: 0 +} + +.uk-grid-collapse>* { + padding-left: 0 +} + +.uk-grid-collapse+.uk-grid-collapse, +.uk-grid-collapse>.uk-grid-margin, +.uk-grid-collapse>*>.uk-panel+.uk-panel { + margin-top: 0 +} + +.uk-grid-small { + margin-left: -10px +} + +.uk-grid-small>* { + padding-left: 10px +} + +.uk-grid-small+.uk-grid-small, +.uk-grid-small>.uk-grid-margin, +.uk-grid-small>*>.uk-panel+.uk-panel { + margin-top: 10px +} + +.uk-grid-medium { + margin-left: -25px +} + +.uk-grid-medium>* { + padding-left: 25px +} + +.uk-grid-medium+.uk-grid-medium, +.uk-grid-medium>.uk-grid-margin, +.uk-grid-medium>*>.uk-panel+.uk-panel { + margin-top: 25px +} + +.uk-grid-divider:not(:empty) { + margin-left: -25px; + margin-right: -25px +} + +.uk-grid-divider>* { + padding-left: 25px; + padding-right: 25px +} + +.uk-grid-divider>[class*='uk-width-1-']:not(.uk-width-1-1):nth-child(n+2), +.uk-grid-divider>[class*='uk-width-2-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-3-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-4-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-5-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-6-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-7-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-8-']:nth-child(n+2), +.uk-grid-divider>[class*='uk-width-9-']:nth-child(n+2) { + border-left: 1px solid #ddd +} + +@media (min-width:768px) { + .uk-grid-divider>[class*='uk-width-medium-']:not(.uk-width-medium-1-1):nth-child(n+2) { + border-left: 1px solid #ddd + } +} + +@media (min-width:960px) { + .uk-grid-divider>[class*='uk-width-large-']:not(.uk-width-large-1-1):nth-child(n+2) { + border-left: 1px solid #ddd + } +} + +@media (min-width:1220px) { + .uk-grid-divider:not(: empty) { + margin-left: -35px; + margin-right: -35px + } + .uk-grid-divider>* { + padding-left: 35px; + padding-right: 35px + } + .uk-grid-divider:empty { + margin-top: 35px; + margin-bottom: 35px + } +} + +.uk-grid-divider:empty { + margin-top: 25px; + margin-bottom: 25px; + border-top: 1px solid #ddd +} + +.uk-grid-match>* { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap +} + +.uk-grid-match>*>* { + -ms-flex: none; + -webkit-flex: none; + flex: none; + box-sizing: border-box; + width: 100% +} + +[class*='uk-grid-width']>* { + box-sizing: border-box; + width: 100% +} + +.uk-grid-width-1-2>* { + width: 50% +} + +.uk-grid-width-1-3>* { + width: 33.333% +} + +.uk-grid-width-1-4>* { + width: 25% +} + +.uk-grid-width-1-5>* { + width: 20% +} + +.uk-grid-width-1-6>* { + width: 16.666% +} + +.uk-grid-width-1-10>* { + width: 10% +} + +.uk-grid-width-auto>* { + width: auto +} + +@media (min-width:480px) { + .uk-grid-width-small-1-1>* { + width: 100% + } + .uk-grid-width-small-1-2>* { + width: 50% + } + .uk-grid-width-small-1-3>* { + width: 33.333% + } + .uk-grid-width-small-1-4>* { + width: 25% + } + .uk-grid-width-small-1-5>* { + width: 20% + } + .uk-grid-width-small-1-6>* { + width: 16.666% + } + .uk-grid-width-small-1-10>* { + width: 10% + } +} + +@media (min-width:768px) { + .uk-grid-width-medium-1-1>* { + width: 100% + } + .uk-grid-width-medium-1-2>* { + width: 50% + } + .uk-grid-width-medium-1-3>* { + width: 33.333% + } + .uk-grid-width-medium-1-4>* { + width: 25% + } + .uk-grid-width-medium-1-5>* { + width: 20% + } + .uk-grid-width-medium-1-6>* { + width: 16.666% + } + .uk-grid-width-medium-1-10>* { + width: 10% + } +} + +@media (min-width:960px) { + .uk-grid-width-large-1-1>* { + width: 100% + } + .uk-grid-width-large-1-2>* { + width: 50% + } + .uk-grid-width-large-1-3>* { + width: 33.333% + } + .uk-grid-width-large-1-4>* { + width: 25% + } + .uk-grid-width-large-1-5>* { + width: 20% + } + .uk-grid-width-large-1-6>* { + width: 16.666% + } + .uk-grid-width-large-1-10>* { + width: 10% + } +} + +@media (min-width:1220px) { + .uk-grid-width-xlarge-1-1>* { + width: 100% + } + .uk-grid-width-xlarge-1-2>* { + width: 50% + } + .uk-grid-width-xlarge-1-3>* { + width: 33.333% + } + .uk-grid-width-xlarge-1-4>* { + width: 25% + } + .uk-grid-width-xlarge-1-5>* { + width: 20% + } + .uk-grid-width-xlarge-1-6>* { + width: 16.666% + } + .uk-grid-width-xlarge-1-10>* { + width: 10% + } +} + +[class*='uk-width'] { + box-sizing: border-box; + width: 100% +} + +.uk-width-1-1 { + width: 100% +} + +.uk-width-1-2, +.uk-width-2-4, +.uk-width-3-6, +.uk-width-5-10 { + width: 50% +} + +.uk-width-1-3, +.uk-width-2-6 { + width: 33.333% +} + +.uk-width-2-3, +.uk-width-4-6 { + width: 66.666% +} + +.uk-width-1-4 { + width: 25% +} + +.uk-width-3-4 { + width: 75% +} + +.uk-width-1-5, +.uk-width-2-10 { + width: 20% +} + +.uk-width-2-5, +.uk-width-4-10 { + width: 40% +} + +.uk-width-3-5, +.uk-width-6-10 { + width: 60% +} + +.uk-width-4-5, +.uk-width-8-10 { + width: 80% +} + +.uk-width-1-6 { + width: 16.666% +} + +.uk-width-5-6 { + width: 83.333% +} + +.uk-width-1-10 { + width: 10% +} + +.uk-width-3-10 { + width: 30% +} + +.uk-width-7-10 { + width: 70% +} + +.uk-width-9-10 { + width: 90% +} + +@media (min-width:480px) { + .uk-width-small-1-1 { + width: 100% + } + .uk-width-small-1-2, + .uk-width-small-2-4, + .uk-width-small-3-6, + .uk-width-small-5-10 { + width: 50% + } + .uk-width-small-1-3, + .uk-width-small-2-6 { + width: 33.333% + } + .uk-width-small-2-3, + .uk-width-small-4-6 { + width: 66.666% + } + .uk-width-small-1-4 { + width: 25% + } + .uk-width-small-3-4 { + width: 75% + } + .uk-width-small-1-5, + .uk-width-small-2-10 { + width: 20% + } + .uk-width-small-2-5, + .uk-width-small-4-10 { + width: 40% + } + .uk-width-small-3-5, + .uk-width-small-6-10 { + width: 60% + } + .uk-width-small-4-5, + .uk-width-small-8-10 { + width: 80% + } + .uk-width-small-1-6 { + width: 16.666% + } + .uk-width-small-5-6 { + width: 83.333% + } + .uk-width-small-1-10 { + width: 10% + } + .uk-width-small-3-10 { + width: 30% + } + .uk-width-small-7-10 { + width: 70% + } + .uk-width-small-9-10 { + width: 90% + } +} + +@media (min-width:768px) { + .uk-width-medium-1-1 { + width: 100% + } + .uk-width-medium-1-2, + .uk-width-medium-2-4, + .uk-width-medium-3-6, + .uk-width-medium-5-10 { + width: 50% + } + .uk-width-medium-1-3, + .uk-width-medium-2-6 { + width: 33.333% + } + .uk-width-medium-2-3, + .uk-width-medium-4-6 { + width: 66.666% + } + .uk-width-medium-1-4 { + width: 25% + } + .uk-width-medium-3-4 { + width: 75% + } + .uk-width-medium-1-5, + .uk-width-medium-2-10 { + width: 20% + } + .uk-width-medium-2-5, + .uk-width-medium-4-10 { + width: 40% + } + .uk-width-medium-3-5, + .uk-width-medium-6-10 { + width: 60% + } + .uk-width-medium-4-5, + .uk-width-medium-8-10 { + width: 80% + } + .uk-width-medium-1-6 { + width: 16.666% + } + .uk-width-medium-5-6 { + width: 83.333% + } + .uk-width-medium-1-10 { + width: 10% + } + .uk-width-medium-3-10 { + width: 30% + } + .uk-width-medium-7-10 { + width: 70% + } + .uk-width-medium-9-10 { + width: 90% + } +} + +@media (min-width:960px) { + .uk-width-large-1-1 { + width: 100% + } + .uk-width-large-1-2, + .uk-width-large-2-4, + .uk-width-large-3-6, + .uk-width-large-5-10 { + width: 50% + } + .uk-width-large-1-3, + .uk-width-large-2-6 { + width: 33.333% + } + .uk-width-large-2-3, + .uk-width-large-4-6 { + width: 66.666% + } + .uk-width-large-1-4 { + width: 25% + } + .uk-width-large-3-4 { + width: 75% + } + .uk-width-large-1-5, + .uk-width-large-2-10 { + width: 20% + } + .uk-width-large-2-5, + .uk-width-large-4-10 { + width: 40% + } + .uk-width-large-3-5, + .uk-width-large-6-10 { + width: 60% + } + .uk-width-large-4-5, + .uk-width-large-8-10 { + width: 80% + } + .uk-width-large-1-6 { + width: 16.666% + } + .uk-width-large-5-6 { + width: 83.333% + } + .uk-width-large-1-10 { + width: 10% + } + .uk-width-large-3-10 { + width: 30% + } + .uk-width-large-7-10 { + width: 70% + } + .uk-width-large-9-10 { + width: 90% + } +} + +@media (min-width:1220px) { + .uk-width-xlarge-1-1 { + width: 100% + } + .uk-width-xlarge-1-2, + .uk-width-xlarge-2-4, + .uk-width-xlarge-3-6, + .uk-width-xlarge-5-10 { + width: 50% + } + .uk-width-xlarge-1-3, + .uk-width-xlarge-2-6 { + width: 33.333% + } + .uk-width-xlarge-2-3, + .uk-width-xlarge-4-6 { + width: 66.666% + } + .uk-width-xlarge-1-4 { + width: 25% + } + .uk-width-xlarge-3-4 { + width: 75% + } + .uk-width-xlarge-1-5, + .uk-width-xlarge-2-10 { + width: 20% + } + .uk-width-xlarge-2-5, + .uk-width-xlarge-4-10 { + width: 40% + } + .uk-width-xlarge-3-5, + .uk-width-xlarge-6-10 { + width: 60% + } + .uk-width-xlarge-4-5, + .uk-width-xlarge-8-10 { + width: 80% + } + .uk-width-xlarge-1-6 { + width: 16.666% + } + .uk-width-xlarge-5-6 { + width: 83.333% + } + .uk-width-xlarge-1-10 { + width: 10% + } + .uk-width-xlarge-3-10 { + width: 30% + } + .uk-width-xlarge-7-10 { + width: 70% + } + .uk-width-xlarge-9-10 { + width: 90% + } +} + +@media (min-width:768px) { + [class*='uk-push-'], + [class*='uk-pull-'] { + position: relative + } + .uk-push-1-2, + .uk-push-2-4, + .uk-push-3-6, + .uk-push-5-10 { + left: 50% + } + .uk-push-1-3, + .uk-push-2-6 { + left: 33.333% + } + .uk-push-2-3, + .uk-push-4-6 { + left: 66.666% + } + .uk-push-1-4 { + left: 25% + } + .uk-push-3-4 { + left: 75% + } + .uk-push-1-5, + .uk-push-2-10 { + left: 20% + } + .uk-push-2-5, + .uk-push-4-10 { + left: 40% + } + .uk-push-3-5, + .uk-push-6-10 { + left: 60% + } + .uk-push-4-5, + .uk-push-8-10 { + left: 80% + } + .uk-push-1-6 { + left: 16.666% + } + .uk-push-5-6 { + left: 83.333% + } + .uk-push-1-10 { + left: 10% + } + .uk-push-3-10 { + left: 30% + } + .uk-push-7-10 { + left: 70% + } + .uk-push-9-10 { + left: 90% + } + .uk-pull-1-2, + .uk-pull-2-4, + .uk-pull-3-6, + .uk-pull-5-10 { + left: -50% + } + .uk-pull-1-3, + .uk-pull-2-6 { + left: -33.333% + } + .uk-pull-2-3, + .uk-pull-4-6 { + left: -66.666% + } + .uk-pull-1-4 { + left: -25% + } + .uk-pull-3-4 { + left: -75% + } + .uk-pull-1-5, + .uk-pull-2-10 { + left: -20% + } + .uk-pull-2-5, + .uk-pull-4-10 { + left: -40% + } + .uk-pull-3-5, + .uk-pull-6-10 { + left: -60% + } + .uk-pull-4-5, + .uk-pull-8-10 { + left: -80% + } + .uk-pull-1-6 { + left: -16.666% + } + .uk-pull-5-6 { + left: -83.333% + } + .uk-pull-1-10 { + left: -10% + } + .uk-pull-3-10 { + left: -30% + } + .uk-pull-7-10 { + left: -70% + } + .uk-pull-9-10 { + left: -90% + } +} + +.uk-panel { + display: block; + position: relative +} + +.uk-panel, +.uk-panel:hover { + text-decoration: none +} + +.uk-panel:before, +.uk-panel:after { + content: ""; + display: table +} + +.uk-panel:after { + clear: both +} + +.uk-panel>:not(.uk-panel-title):last-child { + margin-bottom: 0 +} + +.uk-panel-title { + margin-top: 0; + margin-bottom: 15px; + font-size: 18px; + line-height: 24px; + font-weight: normal; + text-transform: none; + color: #444 +} + +.uk-panel-badge { + position: absolute; + top: 0; + right: 0; + z-index: 1 +} + +.uk-panel-teaser { + margin-bottom: 15px +} + +.uk-panel-body { + padding: 15px +} + +.uk-panel-box { + padding: 15px; + background: #fafafa; + color: #444; + border: 1px solid #ddd; + border-radius: 4px +} + +.uk-panel-box-hover:hover { + color: #444 +} + +.uk-panel-box .uk-panel-title { + color: #444 +} + +.uk-panel-box .uk-panel-badge { + top: 10px; + right: 10px +} + +.uk-panel-box>.uk-panel-teaser { + margin-top: -16px; + margin-left: -16px; + margin-right: -16px +} + +.uk-panel-box>.uk-nav-side { + margin: 0 -15px +} + +.uk-panel-box-primary { + background-color: #ebf7fd; + color: #2d7091; + border-color: rgba(45, 112, 145, 0.3) +} + +.uk-panel-box-primary-hover:hover { + color: #2d7091 +} + +.uk-panel-box-primary .uk-panel-title { + color: #2d7091 +} + +.uk-panel-box-secondary { + background-color: #fff; + color: #444 +} + +.uk-panel-box-secondary-hover:hover { + color: #444 +} + +.uk-panel-box-secondary .uk-panel-title { + color: #444 +} + +.uk-panel-hover { + padding: 15px; + color: #444; + border: 1px solid transparent; + border-radius: 4px +} + +.uk-panel-hover:hover { + background: #fafafa; + color: #444; + border-color: #ddd +} + +.uk-panel-hover .uk-panel-badge { + top: 10px; + right: 10px +} + +.uk-panel-hover>.uk-panel-teaser { + margin-top: -16px; + margin-left: -16px; + margin-right: -16px +} + +.uk-panel-header .uk-panel-title { + padding-bottom: 10px; + border-bottom: 1px solid #ddd; + color: #444 +} + +.uk-panel-space { + padding: 30px +} + +.uk-panel-space .uk-panel-badge { + top: 30px; + right: 30px +} + +.uk-panel+.uk-panel-divider { + margin-top: 50px !important +} + +.uk-panel+.uk-panel-divider:before { + content: ""; + display: block; + position: absolute; + top: -25px; + left: 0; + right: 0; + border-top: 1px solid #ddd +} + +@media (min-width:1220px) { + .uk-panel+.uk-panel-divider { + margin-top: 70px !important + } + .uk-panel+.uk-panel-divider:before { + top: -35px + } +} + +.uk-panel-box .uk-panel-teaser { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + overflow: hidden; + -webkit-transform: translateZ(0) +} + +.uk-block { + position: relative; + box-sizing: border-box; + padding-top: 20px; + padding-bottom: 20px +} + +@media (min-width:768px) { + .uk-block { + padding-top: 50px; + padding-bottom: 50px + } +} + +.uk-block:before, +.uk-block:after { + content: ""; + display: table +} + +.uk-block:after { + clear: both +} + +.uk-block>:last-child { + margin-bottom: 0 +} + +.uk-block-large { + padding-top: 20px; + padding-bottom: 20px +} + +@media (min-width:768px) { + .uk-block-large { + padding-top: 50px; + padding-bottom: 50px + } +} + +@media (min-width:960px) { + .uk-block-large { + padding-top: 100px; + padding-bottom: 100px + } +} + +.uk-block-default { + background: #fff +} + +.uk-block-muted { + background: #f9f9f9 +} + +.uk-block-primary { + background: #00a8e6 +} + +.uk-block-secondary { + background: #222 +} + +.uk-block-default+.uk-block-default, +.uk-block-muted+.uk-block-muted, +.uk-block-primary+.uk-block-primary, +.uk-block-secondary+.uk-block-secondary { + padding-top: 0 +} + +.uk-article:before, +.uk-article:after { + content: ""; + display: table +} + +.uk-article:after { + clear: both +} + +.uk-article>:last-child { + margin-bottom: 0 +} + +.uk-article+.uk-article { + margin-top: 25px +} + +.uk-article-title { + font-size: 36px; + line-height: 42px; + font-weight: normal; + text-transform: none +} + +.uk-article-title a { + color: inherit; + text-decoration: none +} + +.uk-article-meta { + font-size: 12px; + line-height: 18px; + color: #999 +} + +.uk-article-lead { + color: #444; + font-size: 18px; + line-height: 24px; + font-weight: normal +} + +.uk-article-divider { + margin-bottom: 25px; + border-color: #ddd +} + +*+.uk-article-divider { + margin-top: 25px +} + +.uk-article+.uk-article { + padding-top: 25px; + border-top: 1px solid #ddd +} + +.uk-comment-header { + margin-bottom: 15px; + padding: 10px; + border: 1px solid #ddd; + border-radius: 4px; + background: #fafafa +} + +.uk-comment-header:before, +.uk-comment-header:after { + content: ""; + display: table +} + +.uk-comment-header:after { + clear: both +} + +.uk-comment-avatar { + margin-right: 15px; + float: left +} + +.uk-comment-title { + margin: 5px 0 0 0; + font-size: 16px; + line-height: 22px +} + +.uk-comment-meta { + margin: 2px 0 0 0; + font-size: 11px; + line-height: 16px; + color: #999 +} + +.uk-comment-body { + padding-left: 10px; + padding-right: 10px +} + +.uk-comment-body>:last-child { + margin-bottom: 0 +} + +.uk-comment-list { + padding: 0; + list-style: none +} + +.uk-comment-list .uk-comment+ul { + margin: 25px 0 0 0; + list-style: none +} + +.uk-comment-list>li:nth-child(n+2), +.uk-comment-list .uk-comment+ul>li:nth-child(n+2) { + margin-top: 25px +} + +@media (min-width:768px) { + .uk-comment-list .uk-comment+ul { + padding-left: 100px + } +} + +.uk-comment-primary .uk-comment-header { + border-color: rgba(45, 112, 145, 0.3); + background-color: #ebf7fd; + color: #2d7091; + text-shadow: 0 1px 0 #fff +} + +.uk-cover-background { + background-position: 50% 50%; + background-size: cover; + background-repeat: no-repeat +} + +.uk-cover { + overflow: hidden +} + +.uk-cover-object { + width: auto; + height: auto; + min-width: 100%; + min-height: 100%; + max-width: none; + position: relative; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%) +} + +[data-uk-cover] { + position: relative; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%) +} + +.uk-nav, +.uk-nav ul { + margin: 0; + padding: 0; + list-style: none +} + +.uk-nav li>a { + display: block; + text-decoration: none +} + +.uk-nav>li>a { + padding: 5px 15px +} + +.uk-nav ul { + padding-left: 15px +} + +.uk-nav ul a { + padding: 2px 0 +} + +.uk-nav li>a>div { + font-size: 12px; + line-height: 18px +} + +.uk-nav-header { + padding: 5px 15px; + text-transform: uppercase; + font-weight: bold; + font-size: 12px +} + +.uk-nav-header:not(:first-child) { + margin-top: 15px +} + +.uk-nav-divider { + margin: 9px 15px +} + +ul.uk-nav-sub { + padding: 5px 0 5px 15px +} + +.uk-nav-parent-icon>.uk-parent>a:after { + content: "\f104"; + width: 20px; + margin-right: -10px; + float: right; + font-family: FontAwesome; + text-align: center +} + +.uk-nav-parent-icon>.uk-parent.uk-open>a:after { + content: "\f107" +} + +.uk-nav-side>li>a { + color: #444 +} + +.uk-nav-side>li>a:hover, +.uk-nav-side>li>a:focus { + background: rgba(0, 0, 0, 0.03); + color: #444; + outline: none; + box-shadow: inset 0 0 1px rgba(0, 0, 0, 0.1); + text-shadow: 0 -1px 0 #fff +} + +.uk-nav-side>li.uk-active>a { + background: #009dd8; + color: #fff; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-nav-side .uk-nav-header { + color: #444 +} + +.uk-nav-side .uk-nav-divider { + border-top: 1px solid #ddd; + box-shadow: 0 1px 0 #fff +} + +.uk-nav-side ul a { + color: #07d +} + +.uk-nav-side ul a:hover { + color: #059 +} + +.uk-nav-dropdown>li>a { + color: #444 +} + +.uk-nav-dropdown>li>a:hover, +.uk-nav-dropdown>li>a:focus { + background: #009dd8; + color: #fff; + outline: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-nav-dropdown .uk-nav-header { + color: #999 +} + +.uk-nav-dropdown .uk-nav-divider { + border-top: 1px solid #ddd +} + +.uk-nav-dropdown ul a { + color: #07d +} + +.uk-nav-dropdown ul a:hover { + color: #059 +} + +.uk-nav-navbar>li>a { + color: #444 +} + +.uk-nav-navbar>li>a:hover, +.uk-nav-navbar>li>a:focus { + background: #009dd8; + color: #fff; + outline: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-nav-navbar .uk-nav-header { + color: #999 +} + +.uk-nav-navbar .uk-nav-divider { + border-top: 1px solid #ddd +} + +.uk-nav-navbar ul a { + color: #07d +} + +.uk-nav-navbar ul a:hover { + color: #059 +} + +.uk-nav-offcanvas>li>a { + color: #ccc; + padding: 10px 15px; + border-top: 1px solid rgba(0, 0, 0, 0.3); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5) +} + +.uk-nav-offcanvas>.uk-open>a, +html:not(.uk-touch) .uk-nav-offcanvas>li>a:hover, +html:not(.uk-touch) .uk-nav-offcanvas>li>a:focus { + background: #404040; + color: #fff; + outline: none +} + +html .uk-nav.uk-nav-offcanvas>li.uk-active>a { + background: #1a1a1a; + color: #fff; + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3) +} + +.uk-nav-offcanvas .uk-nav-header { + color: #777; + margin-top: 0; + border-top: 1px solid rgba(0, 0, 0, 0.3); + background: #404040; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5) +} + +.uk-nav-offcanvas .uk-nav-divider { + border-top: 1px solid rgba(255, 255, 255, 0.01); + margin: 0; + height: 4px; + background: rgba(0, 0, 0, 0.2); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3) +} + +.uk-nav-offcanvas ul a { + color: #ccc +} + +html:not(.uk-touch) .uk-nav-offcanvas ul a:hover { + color: #fff +} + +.uk-nav-offcanvas { + border-bottom: 1px solid rgba(0, 0, 0, 0.3); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) +} + +.uk-nav-offcanvas .uk-nav-sub { + border-top: 1px solid rgba(0, 0, 0, 0.3); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05) +} + +.uk-navbar { + background: #f7f7f7; + color: #444; + border: 1px solid rgba(0, 0, 0, 0.1); + border-bottom-color: rgba(0, 0, 0, 0.3); + border-radius: 4px; + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #fff, #eee); + background-image: linear-gradient(to bottom, #fff, #eee) +} + +.uk-navbar:before, +.uk-navbar:after { + content: ""; + display: table +} + +.uk-navbar:after { + clear: both +} + +.uk-navbar-nav { + margin: 0; + padding: 0; + list-style: none; + float: left +} + +.uk-navbar-nav>li { + float: left; + position: relative +} + +.uk-navbar-nav>li>a { + display: block; + box-sizing: border-box; + text-decoration: none; + height: 41px; + padding: 0 15px; + line-height: 40px; + color: #444; + font-size: 14px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: normal; + margin-top: -1px; + margin-left: -1px; + border: 1px solid transparent; + border-bottom-width: 0; + text-shadow: 0 1px 0 #fff +} + +.uk-navbar-nav>li>a[href='#'] { + cursor: text +} + +.uk-navbar-nav>li:hover>a, +.uk-navbar-nav>li>a:focus, +.uk-navbar-nav>li.uk-open>a { + background-color: transparent; + color: #444; + outline: none; + position: relative; + z-index: 1; + border-left-color: rgba(0, 0, 0, 0.1); + border-right-color: rgba(0, 0, 0, 0.1); + border-top-color: rgba(0, 0, 0, 0.1); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-navbar-nav>li>a:active { + background-color: #f5f5f5; + color: #444; + border-left-color: rgba(0, 0, 0, 0.1); + border-right-color: rgba(0, 0, 0, 0.1); + border-top-color: rgba(0, 0, 0, 0.2); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-navbar-nav>li.uk-active>a { + background-color: #fafafa; + color: #444; + border-left-color: rgba(0, 0, 0, 0.1); + border-right-color: rgba(0, 0, 0, 0.1); + border-top-color: rgba(0, 0, 0, 0.2); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-navbar-nav .uk-navbar-nav-subtitle { + line-height: 28px +} + +.uk-navbar-nav-subtitle>div { + margin-top: -6px; + font-size: 10px; + line-height: 12px +} + +.uk-navbar-content, +.uk-navbar-brand, +.uk-navbar-toggle { + box-sizing: border-box; + display: block; + height: 41px; + padding: 0 15px; + float: left; + margin-top: -1px; + text-shadow: 0 1px 0 #fff +} + +.uk-navbar-content:before, +.uk-navbar-brand:before, +.uk-navbar-toggle:before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: middle +} + +.uk-navbar-content+.uk-navbar-content:not(.uk-navbar-center) { + padding-left: 0 +} + +.uk-navbar-content>a:not([class]) { + color: #07d +} + +.uk-navbar-content>a:not([class]):hover { + color: #059 +} + +.uk-navbar-brand { + font-size: 18px; + color: #444; + text-decoration: none +} + +.uk-navbar-brand:hover, +.uk-navbar-brand:focus { + color: #444; + text-decoration: none; + outline: none +} + +.uk-navbar-toggle { + font-size: 18px; + color: #444; + text-decoration: none +} + +.uk-navbar-toggle:hover, +.uk-navbar-toggle:focus { + color: #444; + text-decoration: none; + outline: none +} + +.uk-navbar-toggle:after { + content: "\f0c9"; + font-family: FontAwesome; + vertical-align: middle +} + +.uk-navbar-toggle-alt:after { + content: "\f002" +} + +.uk-navbar-center { + float: none; + text-align: center; + max-width: 50%; + margin-left: auto; + margin-right: auto +} + +.uk-navbar-flip { + float: right +} + +.uk-navbar-nav:first-child>li:first-child>a { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px +} + +.uk-navbar-flip .uk-navbar-nav>li>a { + margin-left: 0; + margin-right: -1px +} + +.uk-navbar-flip .uk-navbar-nav:first-child>li:first-child>a { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.uk-navbar-flip .uk-navbar-nav:last-child>li:last-child>a { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px +} + +.uk-navbar-attached { + border-top-color: transparent; + border-left-color: transparent; + border-right-color: transparent; + border-radius: 0 +} + +.uk-navbar-attached .uk-navbar-nav>li>a { + border-radius: 0 !important +} + +.uk-subnav { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -10px; + margin-top: -10px; + padding: 0; + list-style: none +} + +.uk-subnav>* { + -ms-flex: none; + -webkit-flex: none; + flex: none; + padding-left: 10px; + margin-top: 10px; + position: relative +} + +.uk-subnav:before, +.uk-subnav:after { + content: ""; + display: block; + overflow: hidden +} + +.uk-subnav:after { + clear: both +} + +.uk-subnav>* { + float: left +} + +.uk-subnav>*>* { + display: inline-block; + color: #444 +} + +.uk-subnav>*>:hover, +.uk-subnav>*>:focus { + color: #07d; + text-decoration: none +} + +.uk-subnav>.uk-active>* { + color: #07d +} + +.uk-subnav-line>:before { + content: ""; + display: inline-block; + height: 10px; + vertical-align: middle +} + +.uk-subnav-line>:nth-child(n+2):before { + margin-right: 10px; + border-left: 1px solid #ddd +} + +.uk-subnav-pill>*>* { + padding: 3px 9px; + border-radius: 4px +} + +.uk-subnav-pill>*>:hover, +.uk-subnav-pill>*>:focus { + background: #fafafa; + color: #444; + text-decoration: none; + outline: none; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1) +} + +.uk-subnav-pill>.uk-active>* { + background: #009dd8; + color: #fff; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2) +} + +.uk-subnav>.uk-disabled>* { + background: none; + color: #999; + text-decoration: none; + cursor: text; + box-shadow: none +} + +.uk-breadcrumb { + padding: 0; + list-style: none; + font-size: 0.001px +} + +.uk-breadcrumb>li { + font-size: 1rem; + vertical-align: top +} + +.uk-breadcrumb>li, +.uk-breadcrumb>li>a, +.uk-breadcrumb>li>span { + display: inline-block +} + +.uk-breadcrumb>li:nth-child(n+2):before { + content: "/"; + display: inline-block; + margin: 0 8px +} + +.uk-breadcrumb>li:not(.uk-active)>span { + color: #999 +} + +.uk-pagination { + padding: 0; + list-style: none; + text-align: center; + font-size: 0.001px +} + +.uk-pagination:before, +.uk-pagination:after { + content: ""; + display: table +} + +.uk-pagination:after { + clear: both +} + +.uk-pagination>li { + display: inline-block; + font-size: 1rem; + vertical-align: top +} + +.uk-pagination>li:nth-child(n+2) { + margin-left: 5px +} + +.uk-pagination>li>a, +.uk-pagination>li>span { + display: inline-block; + min-width: 16px; + padding: 3px 5px; + line-height: 20px; + text-decoration: none; + box-sizing: content-box; + text-align: center; + border-radius: 4px +} + +.uk-pagination>li>a { + background: #f7f7f7; + color: #444; + border: 1px solid rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.3); + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #fff, #eee); + background-image: linear-gradient(to bottom, #fff, #eee); + text-shadow: 0 1px 0 #fff +} + +.uk-pagination>li>a:hover, +.uk-pagination>li>a:focus { + background-color: #fafafa; + color: #444; + outline: none; + background-image: none +} + +.uk-pagination>li>a:active { + background-color: #f5f5f5; + color: #444; + border-color: rgba(0, 0, 0, 0.2); + border-top-color: rgba(0, 0, 0, 0.3); + background-image: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-pagination>.uk-active>span { + background: #009dd8; + color: #fff; + border: 1px solid rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.4); + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #00b4f5, #008dc5); + background-image: linear-gradient(to bottom, #00b4f5, #008dc5); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-pagination>.uk-disabled>span { + background-color: #fafafa; + color: #999; + border: 1px solid rgba(0, 0, 0, 0.2); + text-shadow: 0 1px 0 #fff +} + +.uk-pagination-previous { + float: left +} + +.uk-pagination-next { + float: right +} + +.uk-pagination-left { + text-align: left +} + +.uk-pagination-right { + text-align: right +} + +.uk-tab { + margin: 0; + padding: 0; + list-style: none; + border-bottom: 1px solid #ddd +} + +.uk-tab:before, +.uk-tab:after { + content: ""; + display: table +} + +.uk-tab:after { + clear: both +} + +.uk-tab>li { + margin-bottom: -1px; + float: left; + position: relative +} + +.uk-tab>li>a { + display: block; + padding: 8px 12px 8px 12px; + border: 1px solid transparent; + border-bottom-width: 0; + color: #07d; + text-decoration: none; + border-radius: 4px 4px 0 0; + text-shadow: 0 1px 0 #fff +} + +.uk-tab>li:nth-child(n+2)>a { + margin-left: 5px +} + +.uk-tab>li>a:hover, +.uk-tab>li>a:focus, +.uk-tab>li.uk-open>a { + border-color: #ddd; + background: #fafafa; + color: #059; + outline: none +} + +.uk-tab>li:not(.uk-active)>a:hover, +.uk-tab>li:not(.uk-active)>a:focus, +.uk-tab>li.uk-open:not(.uk-active)>a { + margin-bottom: 1px; + padding-bottom: 7px +} + +.uk-tab>li.uk-active>a { + border-color: #ddd; + border-bottom-color: transparent; + background: #fff; + color: #444 +} + +.uk-tab>li.uk-disabled>a { + color: #999; + cursor: text +} + +.uk-tab>li.uk-disabled>a:hover, +.uk-tab>li.uk-disabled>a:focus, +.uk-tab>li.uk-disabled.uk-active>a { + background: none; + border-color: transparent +} + +.uk-tab-flip>li { + float: right +} + +.uk-tab-flip>li:nth-child(n+2)>a { + margin-left: 0; + margin-right: 5px +} + +.uk-tab>li.uk-tab-responsive>a { + margin-left: 0; + margin-right: 0 +} + +.uk-tab-responsive>a:before { + content: "\f0c9\00a0"; + font-family: FontAwesome +} + +.uk-tab-center { + border-bottom: 1px solid #ddd +} + +.uk-tab-center-bottom { + border-bottom: none; + border-top: 1px solid #ddd +} + +.uk-tab-center:before, +.uk-tab-center:after { + content: ""; + display: table +} + +.uk-tab-center:after { + clear: both +} + +.uk-tab-center .uk-tab { + position: relative; + right: 50%; + border: none; + float: right +} + +.uk-tab-center .uk-tab>li { + position: relative; + right: -50% +} + +.uk-tab-center .uk-tab>li>a { + text-align: center +} + +.uk-tab-bottom { + border-top: 1px solid #ddd; + border-bottom: none +} + +.uk-tab-bottom>li { + margin-top: -1px; + margin-bottom: 0 +} + +.uk-tab-bottom>li>a { + padding-top: 8px; + padding-bottom: 8px; + border-bottom-width: 1px; + border-top-width: 0 +} + +.uk-tab-bottom>li:not(.uk-active)>a:hover, +.uk-tab-bottom>li:not(.uk-active)>a:focus, +.uk-tab-bottom>li.uk-open:not(.uk-active)>a { + margin-bottom: 0; + margin-top: 1px; + padding-bottom: 8px; + padding-top: 7px +} + +.uk-tab-bottom>li.uk-active>a { + border-top-color: transparent; + border-bottom-color: #ddd +} + +.uk-tab-grid { + margin-left: -5px; + border-bottom: none; + position: relative; + z-index: 0 +} + +.uk-tab-grid:before { + display: block; + position: absolute; + left: 5px; + right: 0; + bottom: -1px; + border-top: 1px solid #ddd; + z-index: -1 +} + +.uk-tab-grid>li:first-child>a { + margin-left: 5px +} + +.uk-tab-grid>li>a { + text-align: center +} + +.uk-tab-grid.uk-tab-bottom { + border-top: none +} + +.uk-tab-grid.uk-tab-bottom:before { + top: -1px; + bottom: auto +} + +@media (min-width:768px) { + .uk-tab-left, + .uk-tab-right { + border-bottom: none + } + .uk-tab-left>li, + .uk-tab-right>li { + margin-bottom: 0; + float: none + } + .uk-tab-left>li>a, + .uk-tab-right>li>a { + padding-top: 8px; + padding-bottom: 8px + } + .uk-tab-left>li:nth-child(n+2)>a, + .uk-tab-right>li:nth-child(n+2)>a { + margin-left: 0; + margin-top: 5px + } + .uk-tab-left>li.uk-active>a, + .uk-tab-right>li.uk-active>a { + border-color: #ddd + } + .uk-tab-left { + border-right: 1px solid #ddd + } + .uk-tab-left>li { + margin-right: -1px + } + .uk-tab-left>li>a { + border-bottom-width: 1px; + border-right-width: 0 + } + .uk-tab-left>li:not(.uk-active)>a:hover, + .uk-tab-left>li:not(.uk-active)>a:focus { + margin-bottom: 0; + margin-right: 1px; + padding-bottom: 8px; + padding-right: 11px + } + .uk-tab-left>li.uk-active>a { + border-right-color: transparent + } + .uk-tab-right { + border-left: 1px solid #ddd + } + .uk-tab-right>li { + margin-left: -1px + } + .uk-tab-right>li>a { + border-bottom-width: 1px; + border-left-width: 0 + } + .uk-tab-right>li:not(.uk-active)>a:hover, + .uk-tab-right>li:not(.uk-active)>a:focus { + margin-bottom: 0; + margin-left: 1px; + padding-bottom: 8px; + padding-left: 11px + } + .uk-tab-right>li.uk-active>a { + border-left-color: transparent + } +} + +.uk-tab-bottom>li>a { + border-radius: 0 0 4px 4px +} + +@media (min-width:768px) { + .uk-tab-left>li>a { + border-radius: 4px 0 0 4px + } + .uk-tab-right>li>a { + border-radius: 0 4px 4px 0 + } +} + +.uk-thumbnav { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -10px; + margin-top: -10px; + padding: 0; + list-style: none +} + +.uk-thumbnav>* { + -ms-flex: none; + -webkit-flex: none; + flex: none; + padding-left: 10px; + margin-top: 10px +} + +.uk-thumbnav:before, +.uk-thumbnav:after { + content: ""; + display: block; + overflow: hidden +} + +.uk-thumbnav:after { + clear: both +} + +.uk-thumbnav>* { + float: left +} + +.uk-thumbnav>*>* { + display: block; + background: #fff +} + +.uk-thumbnav>*>*>img { + opacity: .7; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear +} + +.uk-thumbnav>*>:hover>img, +.uk-thumbnav>*>:focus>img { + opacity: 1 +} + +.uk-thumbnav>.uk-active>*>img { + opacity: 1 +} + +.uk-list { + padding: 0; + list-style: none +} + +.uk-list>li:before, +.uk-list>li:after { + content: ""; + display: table +} + +.uk-list>li:after { + clear: both +} + +.uk-list>li>:last-child { + margin-bottom: 0 +} + +.uk-list ul { + margin: 0; + padding-left: 20px; + list-style: none +} + +.uk-list-line>li:nth-child(n+2) { + margin-top: 5px; + padding-top: 5px; + border-top: 1px solid #ddd +} + +.uk-list-striped>li { + padding: 5px 5px; + border-bottom: 1px solid #ddd +} + +.uk-list-striped>li:nth-of-type(odd) { + background: #fafafa +} + +.uk-list-space>li:nth-child(n+2) { + margin-top: 10px +} + +.uk-list-striped>li:first-child { + border-top: 1px solid #ddd +} + +@media (min-width:768px) { + .uk-description-list-horizontal { + overflow: hidden + } + .uk-description-list-horizontal>dt { + width: 160px; + float: left; + clear: both; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap + } + .uk-description-list-horizontal>dd { + margin-left: 180px + } +} + +.uk-description-list-line>dt { + font-weight: normal +} + +.uk-description-list-line>dt:nth-child(n+2) { + margin-top: 5px; + padding-top: 5px; + border-top: 1px solid #ddd +} + +.uk-description-list-line>dd { + color: #999 +} + +.uk-table { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + margin-bottom: 15px +} + +*+.uk-table { + margin-top: 15px +} + +.uk-table th, +.uk-table td { + padding: 8px 8px; + border-bottom: 1px solid #ddd +} + +.uk-table th { + text-align: left +} + +.uk-table td { + vertical-align: top +} + +.uk-table thead th { + vertical-align: bottom +} + +.uk-table caption, +.uk-table tfoot { + font-size: 12px; + font-style: italic +} + +.uk-table caption { + text-align: left; + color: #999 +} + +.uk-table tbody tr.uk-active { + background: #f0f0f0 +} + +.uk-table-middle, +.uk-table-middle td { + vertical-align: middle !important +} + +.uk-table-striped tbody tr:nth-of-type(odd) { + background: #fafafa +} + +.uk-table-condensed td { + padding: 4px 8px +} + +.uk-table-hover tbody tr:hover { + background: #f0f0f0 +} + +.uk-form input, +.uk-form select, +.uk-form textarea { + box-sizing: border-box; + margin: 0; + border-radius: 0; + font: inherit; + color: inherit +} + +.uk-form select { + text-transform: none +} + +.uk-form optgroup { + font: inherit; + font-weight: bold +} + +.uk-form input::-moz-focus-inner { + border: 0; + padding: 0 +} + +.uk-form input[type="checkbox"], +.uk-form input[type="radio"] { + padding: 0 +} + +.uk-form input[type="checkbox"]:not(:disabled), +.uk-form input[type="radio"]:not(:disabled) { + cursor: pointer +} + +.uk-form textarea, +.uk-form input:not([type]), +.uk-form input[type="text"], +.uk-form input[type="password"], +.uk-form input[type="email"], +.uk-form input[type="url"], +.uk-form input[type="search"], +.uk-form input[type="tel"], +.uk-form input[type="number"], +.uk-form input[type="datetime"] { + -webkit-appearance: none +} + +.uk-form input[type="search"]::-webkit-search-cancel-button, +.uk-form input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none +} + +.uk-form input[type="number"]::-webkit-inner-spin-button, +.uk-form input[type="number"]::-webkit-outer-spin-button { + height: auto +} + +.uk-form fieldset { + border: none; + margin: 0; + padding: 0 +} + +.uk-form textarea { + overflow: auto; + vertical-align: top +} + +.uk-form::-moz-placeholder { + opacity: 1 +} + +.uk-form:invalid { + box-shadow: none +} + +.uk-form input:not([type="radio"]):not([type="checkbox"]), +.uk-form select { + vertical-align: middle +} + +.uk-form>:last-child { + margin-bottom: 0 +} + +.uk-form select, +.uk-form textarea, +.uk-form input:not([type]), +.uk-form input[type="text"], +.uk-form input[type="password"], +.uk-form input[type="datetime"], +.uk-form input[type="datetime-local"], +.uk-form input[type="date"], +.uk-form input[type="month"], +.uk-form input[type="time"], +.uk-form input[type="week"], +.uk-form input[type="number"], +.uk-form input[type="email"], +.uk-form input[type="url"], +.uk-form input[type="search"], +.uk-form input[type="tel"], +.uk-form input[type="color"] { + height: 30px; + max-width: 100%; + padding: 4px 6px; + border: 1px solid #ddd; + background: #fff; + color: #444; + -webkit-transition: all linear 0.2s; + transition: all linear 0.2s; + border-radius: 4px +} + +.uk-form select:focus, +.uk-form textarea:focus, +.uk-form input:not([type]):focus, +.uk-form input[type="text"]:focus, +.uk-form input[type="password"]:focus, +.uk-form input[type="datetime"]:focus, +.uk-form input[type="datetime-local"]:focus, +.uk-form input[type="date"]:focus, +.uk-form input[type="month"]:focus, +.uk-form input[type="time"]:focus, +.uk-form input[type="week"]:focus, +.uk-form input[type="number"]:focus, +.uk-form input[type="email"]:focus, +.uk-form input[type="url"]:focus, +.uk-form input[type="search"]:focus, +.uk-form input[type="tel"]:focus, +.uk-form input[type="color"]:focus { + border-color: #99baca; + outline: 0; + background: #f5fbfe; + color: #444 +} + +.uk-form select:disabled, +.uk-form textarea:disabled, +.uk-form input:not([type]):disabled, +.uk-form input[type="text"]:disabled, +.uk-form input[type="password"]:disabled, +.uk-form input[type="datetime"]:disabled, +.uk-form input[type="datetime-local"]:disabled, +.uk-form input[type="date"]:disabled, +.uk-form input[type="month"]:disabled, +.uk-form input[type="time"]:disabled, +.uk-form input[type="week"]:disabled, +.uk-form input[type="number"]:disabled, +.uk-form input[type="email"]:disabled, +.uk-form input[type="url"]:disabled, +.uk-form input[type="search"]:disabled, +.uk-form input[type="tel"]:disabled, +.uk-form input[type="color"]:disabled { + border-color: #ddd; + background-color: #fafafa; + color: #999 +} + +.uk-form:-ms-input-placeholder { + color: #999 !important +} + +.uk-form::-moz-placeholder { + color: #999 +} + +.uk-form::-webkit-input-placeholder { + color: #999 +} + +.uk-form:disabled:-ms-input-placeholder { + color: #999 !important +} + +.uk-form:disabled::-moz-placeholder { + color: #999 +} + +.uk-form:disabled::-webkit-input-placeholder { + color: #999 +} + +.uk-form legend { + width: 100%; + border: 0; + padding: 0; + padding-bottom: 15px; + font-size: 18px; + line-height: 30px +} + +.uk-form legend:after { + content: ""; + display: block; + border-bottom: 1px solid #ddd; + width: 100% +} + +select.uk-form-small, +textarea.uk-form-small, +input[type].uk-form-small, +input:not([type]).uk-form-small { + height: 25px; + padding: 3px 3px; + font-size: 12px +} + +select.uk-form-large, +textarea.uk-form-large, +input[type].uk-form-large, +input:not([type]).uk-form-large { + height: 40px; + padding: 8px 6px; + font-size: 16px +} + +.uk-form textarea, +.uk-form select[multiple], +.uk-form select[size] { + height: auto +} + +.uk-form-danger { + border-color: #dc8d99 !important; + background: #fff7f8 !important; + color: #d85030 !important +} + +.uk-form-success { + border-color: #8ec73b !important; + background: #fafff2 !important; + color: #659f13 !important +} + +.uk-form-blank { + border-color: transparent !important; + border-style: dashed !important; + background: none !important +} + +.uk-form-blank:focus { + border-color: #ddd !important +} + +input.uk-form-width-mini { + width: 40px +} + +select.uk-form-width-mini { + width: 65px +} + +.uk-form-width-small { + width: 130px +} + +.uk-form-width-medium { + width: 200px +} + +.uk-form-width-large { + width: 500px +} + +.uk-form-row:before, +.uk-form-row:after { + content: ""; + display: table +} + +.uk-form-row:after { + clear: both +} + +.uk-form-row+.uk-form-row { + margin-top: 15px +} + +.uk-form-help-inline { + display: inline-block; + margin: 0 0 0 10px +} + +.uk-form-help-block { + margin: 5px 0 0 0 +} + +.uk-form-controls>:first-child { + margin-top: 0 +} + +.uk-form-controls>:last-child { + margin-bottom: 0 +} + +.uk-form-controls-condensed { + margin: 5px 0 +} + +.uk-form-stacked .uk-form-label { + display: block; + margin-bottom: 5px; + font-weight: bold +} + +@media (max-width:959px) { + .uk-form-horizontal .uk-form-label { + display: block; + margin-bottom: 5px; + font-weight: bold + } +} + +@media (min-width:960px) { + .uk-form-horizontal .uk-form-label { + width: 200px; + margin-top: 5px; + float: left + } + .uk-form-horizontal .uk-form-controls { + margin-left: 215px + } + .uk-form-horizontal .uk-form-controls-text { + padding-top: 5px + } +} + +.uk-form-icon { + display: inline-block; + position: relative; + max-width: 100% +} + +.uk-form-icon>[class*='uk-icon-'] { + position: absolute; + top: 50%; + width: 30px; + margin-top: -7px; + font-size: 14px; + color: #999; + text-align: center; + pointer-events: none +} + +.uk-form-icon:not(.uk-form-icon-flip)>input { + padding-left: 30px !important +} + +.uk-form-icon-flip>[class*='uk-icon-'] { + right: 0 +} + +.uk-form-icon-flip>input { + padding-right: 30px !important +} + +.uk-button::-moz-focus-inner { + border: 0; + padding: 0 +} + +.uk-button { + -webkit-appearance: none; + margin: 0; + border: none; + overflow: visible; + font: inherit; + color: #444; + text-transform: none; + display: inline-block; + box-sizing: border-box; + padding: 0 12px; + background: #f7f7f7; + vertical-align: middle; + line-height: 28px; + min-height: 30px; + font-size: 1rem; + text-decoration: none; + text-align: center; + border: 1px solid rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.3); + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #fff, #eee); + background-image: linear-gradient(to bottom, #fff, #eee); + border-radius: 4px; + text-shadow: 0 1px 0 #fff +} + +.uk-button:not(:disabled) { + cursor: pointer +} + +.uk-button:hover, +.uk-button:focus { + background-color: #fafafa; + color: #444; + outline: none; + text-decoration: none; + background-image: none +} + +.uk-button:active, +.uk-button.uk-active { + background-color: #f5f5f5; + color: #444; + border-color: rgba(0, 0, 0, 0.2); + border-top-color: rgba(0, 0, 0, 0.3); + background-image: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-button-primary { + background-color: #009dd8; + color: #fff; + background-image: -webkit-linear-gradient(top, #00b4f5, #008dc5); + background-image: linear-gradient(to bottom, #00b4f5, #008dc5); + border-color: rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.4); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-button-primary:hover, +.uk-button-primary:focus { + background-color: #00aff2; + color: #fff; + background-image: none +} + +.uk-button-primary:active, +.uk-button-primary.uk-active { + background-color: #008abf; + color: #fff; + background-image: none; + border-color: rgba(0, 0, 0, 0.2); + border-top-color: rgba(0, 0, 0, 0.4); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2) +} + +.uk-button-success { + background-color: #82bb42; + color: #fff; + background-image: -webkit-linear-gradient(top, #9fd256, #6fac34); + background-image: linear-gradient(to bottom, #9fd256, #6fac34); + border-color: rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.4); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-button-success:hover, +.uk-button-success:focus { + background-color: #8fce48; + color: #fff; + background-image: none +} + +.uk-button-success:active, +.uk-button-success.uk-active { + background-color: #76b430; + color: #fff; + background-image: none; + border-color: rgba(0, 0, 0, 0.2); + border-top-color: rgba(0, 0, 0, 0.4); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2) +} + +.uk-button-danger { + background-color: #d32c46; + color: #fff; + background-image: -webkit-linear-gradient(top, #ee465a, #c11a39); + background-image: linear-gradient(to bottom, #ee465a, #c11a39); + border-color: rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.4); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-button-danger:hover, +.uk-button-danger:focus { + background-color: #e33551; + color: #fff; + background-image: none +} + +.uk-button-danger:active, +.uk-button-danger.uk-active { + background-color: #c91c37; + color: #fff; + background-image: none; + border-color: rgba(0, 0, 0, 0.2); + border-top-color: rgba(0, 0, 0, 0.4); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2) +} + +.uk-button:disabled { + background-color: #fafafa; + color: #999; + border-color: rgba(0, 0, 0, 0.2); + background-image: none; + box-shadow: none; + text-shadow: 0 1px 0 #fff +} + +.uk-button-link, +.uk-button-link:hover, +.uk-button-link:focus, +.uk-button-link:active, +.uk-button-link.uk-active, +.uk-button-link:disabled { + border-color: transparent; + background: none; + box-shadow: none; + text-shadow: none +} + +.uk-button-link { + color: #07d +} + +.uk-button-link:hover, +.uk-button-link:focus, +.uk-button-link:active, +.uk-button-link.uk-active { + color: #059; + text-decoration: underline +} + +.uk-button-link:disabled { + color: #999 +} + +.uk-button-link:focus { + outline: 1px dotted +} + +.uk-button-mini { + min-height: 20px; + padding: 0 6px; + line-height: 18px; + font-size: 11px +} + +.uk-button-small { + min-height: 25px; + padding: 0 10px; + line-height: 23px; + font-size: 12px +} + +.uk-button-large { + min-height: 40px; + padding: 0 15px; + line-height: 38px; + font-size: 16px; + border-radius: 5px +} + +.uk-button-group { + display: inline-block; + vertical-align: middle; + position: relative; + font-size: 0.001px; + white-space: nowrap +} + +.uk-button-group>* { + display: inline-block +} + +.uk-button-group .uk-button { + vertical-align: top +} + +.uk-button-dropdown { + display: inline-block; + vertical-align: middle; + position: relative +} + +.uk-button-group>.uk-button:not(:first-child):not(:last-child), +.uk-button-group>div:not(:first-child):not(:last-child) .uk-button { + border-radius: 0 +} + +.uk-button-group>.uk-button:first-child, +.uk-button-group>div:first-child .uk-button { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.uk-button-group>.uk-button:last-child, +.uk-button-group>div:last-child .uk-button { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.uk-button-group>.uk-button:nth-child(n+2), +.uk-button-group>div:nth-child(n+2) .uk-button { + margin-left: -1px +} + +.uk-button-group .uk-button:hover, +.uk-button-group .uk-button:active, +.uk-button-group .uk-button.uk-active { + position: relative +} + +@font-face { + font-family: 'FontAwesome'; + /*src: url("../fonts/fontawesome-webfont.woff2") format('woff2'), url("../fonts/fontawesome-webfont.woff") format("woff"), url("../fonts/fontawesome-webfont.ttf") format("truetype");*/ + font-weight: normal; + font-style: normal +} + +[class*='uk-icon-'] { + font-family: FontAwesome; + display: inline-block; + font-weight: normal; + font-style: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale +} + +[class*='uk-icon-'], +[class*='uk-icon-']:hover, +[class*='uk-icon-']:focus { + text-decoration: none +} + +.uk-icon-small { + font-size: 150%; + vertical-align: -10% +} + +.uk-icon-medium { + font-size: 200%; + vertical-align: -16% +} + +.uk-icon-large { + font-size: 250%; + vertical-align: -22% +} + +.uk-icon-justify { + width: 1em; + text-align: center +} + +.uk-icon-spin { + display: inline-block; + -webkit-animation: uk-rotate 2s infinite linear; + animation: uk-rotate 2s infinite linear +} + +.uk-icon-hover { + color: #999 +} + +.uk-icon-hover:hover { + color: #444 +} + +.uk-icon-button { + box-sizing: border-box; + display: inline-block; + width: 35px; + height: 35px; + border-radius: 100%; + background: #f7f7f7; + line-height: 35px; + color: #444; + font-size: 18px; + text-align: center; + border: 1px solid #ccc; + border-bottom-color: #bbb; + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #fff, #eee); + background-image: linear-gradient(to bottom, #fff, #eee); + text-shadow: 0 1px 0 #fff +} + +.uk-icon-button:hover, +.uk-icon-button:focus { + background-color: #fafafa; + color: #444; + outline: none; + background-image: none +} + +.uk-icon-button:active { + background-color: #f5f5f5; + color: #444; + border-color: #ccc; + border-top-color: #bbb; + background-image: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-icon-glass:before { + content: "\f000" +} + +.uk-icon-music:before { + content: "\f001" +} + +.uk-icon-search:before { + content: "\f002" +} + +.uk-icon-envelope-o:before { + content: "\f003" +} + +.uk-icon-heart:before { + content: "\f004" +} + +.uk-icon-star:before { + content: "\f005" +} + +.uk-icon-star-o:before { + content: "\f006" +} + +.uk-icon-user:before { + content: "\f007" +} + +.uk-icon-film:before { + content: "\f008" +} + +.uk-icon-th-large:before { + content: "\f009" +} + +.uk-icon-th:before { + content: "\f00a" +} + +.uk-icon-th-list:before { + content: "\f00b" +} + +.uk-icon-check:before { + content: "\f00c" +} + +.uk-icon-remove:before, +.uk-icon-close:before, +.uk-icon-times:before { + content: "\f00d" +} + +.uk-icon-search-plus:before { + content: "\f00e" +} + +.uk-icon-search-minus:before { + content: "\f010" +} + +.uk-icon-power-off:before { + content: "\f011" +} + +.uk-icon-signal:before { + content: "\f012" +} + +.uk-icon-gear:before, +.uk-icon-cog:before { + content: "\f013" +} + +.uk-icon-trash-o:before { + content: "\f014" +} + +.uk-icon-home:before { + content: "\f015" +} + +.uk-icon-file-o:before { + content: "\f016" +} + +.uk-icon-clock-o:before { + content: "\f017" +} + +.uk-icon-road:before { + content: "\f018" +} + +.uk-icon-download:before { + content: "\f019" +} + +.uk-icon-arrow-circle-o-down:before { + content: "\f01a" +} + +.uk-icon-arrow-circle-o-up:before { + content: "\f01b" +} + +.uk-icon-inbox:before { + content: "\f01c" +} + +.uk-icon-play-circle-o:before { + content: "\f01d" +} + +.uk-icon-rotate-right:before, +.uk-icon-repeat:before { + content: "\f01e" +} + +.uk-icon-refresh:before { + content: "\f021" +} + +.uk-icon-list-alt:before { + content: "\f022" +} + +.uk-icon-lock:before { + content: "\f023" +} + +.uk-icon-flag:before { + content: "\f024" +} + +.uk-icon-headphones:before { + content: "\f025" +} + +.uk-icon-volume-off:before { + content: "\f026" +} + +.uk-icon-volume-down:before { + content: "\f027" +} + +.uk-icon-volume-up:before { + content: "\f028" +} + +.uk-icon-qrcode:before { + content: "\f029" +} + +.uk-icon-barcode:before { + content: "\f02a" +} + +.uk-icon-tag:before { + content: "\f02b" +} + +.uk-icon-tags:before { + content: "\f02c" +} + +.uk-icon-book:before { + content: "\f02d" +} + +.uk-icon-bookmark:before { + content: "\f02e" +} + +.uk-icon-print:before { + content: "\f02f" +} + +.uk-icon-camera:before { + content: "\f030" +} + +.uk-icon-font:before { + content: "\f031" +} + +.uk-icon-bold:before { + content: "\f032" +} + +.uk-icon-italic:before { + content: "\f033" +} + +.uk-icon-text-height:before { + content: "\f034" +} + +.uk-icon-text-width:before { + content: "\f035" +} + +.uk-icon-align-left:before { + content: "\f036" +} + +.uk-icon-align-center:before { + content: "\f037" +} + +.uk-icon-align-right:before { + content: "\f038" +} + +.uk-icon-align-justify:before { + content: "\f039" +} + +.uk-icon-list:before { + content: "\f03a" +} + +.uk-icon-dedent:before, +.uk-icon-outdent:before { + content: "\f03b" +} + +.uk-icon-indent:before { + content: "\f03c" +} + +.uk-icon-video-camera:before { + content: "\f03d" +} + +.uk-icon-photo:before, +.uk-icon-image:before, +.uk-icon-picture-o:before { + content: "\f03e" +} + +.uk-icon-pencil:before { + content: "\f040" +} + +.uk-icon-map-marker:before { + content: "\f041" +} + +.uk-icon-adjust:before { + content: "\f042" +} + +.uk-icon-tint:before { + content: "\f043" +} + +.uk-icon-edit:before, +.uk-icon-pencil-square-o:before { + content: "\f044" +} + +.uk-icon-share-square-o:before { + content: "\f045" +} + +.uk-icon-check-square-o:before { + content: "\f046" +} + +.uk-icon-arrows:before { + content: "\f047" +} + +.uk-icon-step-backward:before { + content: "\f048" +} + +.uk-icon-fast-backward:before { + content: "\f049" +} + +.uk-icon-backward:before { + content: "\f04a" +} + +.uk-icon-play:before { + content: "\f04b" +} + +.uk-icon-pause:before { + content: "\f04c" +} + +.uk-icon-stop:before { + content: "\f04d" +} + +.uk-icon-forward:before { + content: "\f04e" +} + +.uk-icon-fast-forward:before { + content: "\f050" +} + +.uk-icon-step-forward:before { + content: "\f051" +} + +.uk-icon-eject:before { + content: "\f052" +} + +.uk-icon-chevron-left:before { + content: "\f053" +} + +.uk-icon-chevron-right:before { + content: "\f054" +} + +.uk-icon-plus-circle:before { + content: "\f055" +} + +.uk-icon-minus-circle:before { + content: "\f056" +} + +.uk-icon-times-circle:before { + content: "\f057" +} + +.uk-icon-check-circle:before { + content: "\f058" +} + +.uk-icon-question-circle:before { + content: "\f059" +} + +.uk-icon-info-circle:before { + content: "\f05a" +} + +.uk-icon-crosshairs:before { + content: "\f05b" +} + +.uk-icon-times-circle-o:before { + content: "\f05c" +} + +.uk-icon-check-circle-o:before { + content: "\f05d" +} + +.uk-icon-ban:before { + content: "\f05e" +} + +.uk-icon-arrow-left:before { + content: "\f060" +} + +.uk-icon-arrow-right:before { + content: "\f061" +} + +.uk-icon-arrow-up:before { + content: "\f062" +} + +.uk-icon-arrow-down:before { + content: "\f063" +} + +.uk-icon-mail-forward:before, +.uk-icon-share:before { + content: "\f064" +} + +.uk-icon-expand:before { + content: "\f065" +} + +.uk-icon-compress:before { + content: "\f066" +} + +.uk-icon-plus:before { + content: "\f067" +} + +.uk-icon-minus:before { + content: "\f068" +} + +.uk-icon-asterisk:before { + content: "\f069" +} + +.uk-icon-exclamation-circle:before { + content: "\f06a" +} + +.uk-icon-gift:before { + content: "\f06b" +} + +.uk-icon-leaf:before { + content: "\f06c" +} + +.uk-icon-fire:before { + content: "\f06d" +} + +.uk-icon-eye:before { + content: "\f06e" +} + +.uk-icon-eye-slash:before { + content: "\f070" +} + +.uk-icon-warning:before, +.uk-icon-exclamation-triangle:before { + content: "\f071" +} + +.uk-icon-plane:before { + content: "\f072" +} + +.uk-icon-calendar:before { + content: "\f073" +} + +.uk-icon-random:before { + content: "\f074" +} + +.uk-icon-comment:before { + content: "\f075" +} + +.uk-icon-magnet:before { + content: "\f076" +} + +.uk-icon-chevron-up:before { + content: "\f077" +} + +.uk-icon-chevron-down:before { + content: "\f078" +} + +.uk-icon-retweet:before { + content: "\f079" +} + +.uk-icon-shopping-cart:before { + content: "\f07a" +} + +.uk-icon-folder:before { + content: "\f07b" +} + +.uk-icon-folder-open:before { + content: "\f07c" +} + +.uk-icon-arrows-v:before { + content: "\f07d" +} + +.uk-icon-arrows-h:before { + content: "\f07e" +} + +.uk-icon-bar-chart-o:before, +.uk-icon-bar-chart:before { + content: "\f080" +} + +.uk-icon-twitter-square:before { + content: "\f081" +} + +.uk-icon-facebook-square:before { + content: "\f082" +} + +.uk-icon-camera-retro:before { + content: "\f083" +} + +.uk-icon-key:before { + content: "\f084" +} + +.uk-icon-gears:before, +.uk-icon-cogs:before { + content: "\f085" +} + +.uk-icon-comments:before { + content: "\f086" +} + +.uk-icon-thumbs-o-up:before { + content: "\f087" +} + +.uk-icon-thumbs-o-down:before { + content: "\f088" +} + +.uk-icon-star-half:before { + content: "\f089" +} + +.uk-icon-heart-o:before { + content: "\f08a" +} + +.uk-icon-sign-out:before { + content: "\f08b" +} + +.uk-icon-linkedin-square:before { + content: "\f08c" +} + +.uk-icon-thumb-tack:before { + content: "\f08d" +} + +.uk-icon-external-link:before { + content: "\f08e" +} + +.uk-icon-sign-in:before { + content: "\f090" +} + +.uk-icon-trophy:before { + content: "\f091" +} + +.uk-icon-github-square:before { + content: "\f092" +} + +.uk-icon-upload:before { + content: "\f093" +} + +.uk-icon-lemon-o:before { + content: "\f094" +} + +.uk-icon-phone:before { + content: "\f095" +} + +.uk-icon-square-o:before { + content: "\f096" +} + +.uk-icon-bookmark-o:before { + content: "\f097" +} + +.uk-icon-phone-square:before { + content: "\f098" +} + +.uk-icon-twitter:before { + content: "\f099" +} + +.uk-icon-facebook-f:before, +.uk-icon-facebook:before { + content: "\f09a" +} + +.uk-icon-github:before { + content: "\f09b" +} + +.uk-icon-unlock:before { + content: "\f09c" +} + +.uk-icon-credit-card:before { + content: "\f09d" +} + +.uk-icon-rss:before { + content: "\f09e" +} + +.uk-icon-hdd-o:before { + content: "\f0a0" +} + +.uk-icon-bullhorn:before { + content: "\f0a1" +} + +.uk-icon-bell:before { + content: "\f0f3" +} + +.uk-icon-certificate:before { + content: "\f0a3" +} + +.uk-icon-hand-o-right:before { + content: "\f0a4" +} + +.uk-icon-hand-o-left:before { + content: "\f0a5" +} + +.uk-icon-hand-o-up:before { + content: "\f0a6" +} + +.uk-icon-hand-o-down:before { + content: "\f0a7" +} + +.uk-icon-arrow-circle-left:before { + content: "\f0a8" +} + +.uk-icon-arrow-circle-right:before { + content: "\f0a9" +} + +.uk-icon-arrow-circle-up:before { + content: "\f0aa" +} + +.uk-icon-arrow-circle-down:before { + content: "\f0ab" +} + +.uk-icon-globe:before { + content: "\f0ac" +} + +.uk-icon-wrench:before { + content: "\f0ad" +} + +.uk-icon-tasks:before { + content: "\f0ae" +} + +.uk-icon-filter:before { + content: "\f0b0" +} + +.uk-icon-briefcase:before { + content: "\f0b1" +} + +.uk-icon-arrows-alt:before { + content: "\f0b2" +} + +.uk-icon-group:before, +.uk-icon-users:before { + content: "\f0c0" +} + +.uk-icon-chain:before, +.uk-icon-link:before { + content: "\f0c1" +} + +.uk-icon-cloud:before { + content: "\f0c2" +} + +.uk-icon-flask:before { + content: "\f0c3" +} + +.uk-icon-cut:before, +.uk-icon-scissors:before { + content: "\f0c4" +} + +.uk-icon-copy:before, +.uk-icon-files-o:before { + content: "\f0c5" +} + +.uk-icon-paperclip:before { + content: "\f0c6" +} + +.uk-icon-save:before, +.uk-icon-floppy-o:before { + content: "\f0c7" +} + +.uk-icon-square:before { + content: "\f0c8" +} + +.uk-icon-navicon:before, +.uk-icon-reorder:before, +.uk-icon-bars:before { + content: "\f0c9" +} + +.uk-icon-list-ul:before { + content: "\f0ca" +} + +.uk-icon-list-ol:before { + content: "\f0cb" +} + +.uk-icon-strikethrough:before { + content: "\f0cc" +} + +.uk-icon-underline:before { + content: "\f0cd" +} + +.uk-icon-table:before { + content: "\f0ce" +} + +.uk-icon-magic:before { + content: "\f0d0" +} + +.uk-icon-truck:before { + content: "\f0d1" +} + +.uk-icon-pinterest:before { + content: "\f0d2" +} + +.uk-icon-pinterest-square:before { + content: "\f0d3" +} + +.uk-icon-google-plus-square:before { + content: "\f0d4" +} + +.uk-icon-google-plus:before { + content: "\f0d5" +} + +.uk-icon-money:before { + content: "\f0d6" +} + +.uk-icon-caret-down:before { + content: "\f0d7" +} + +.uk-icon-caret-up:before { + content: "\f0d8" +} + +.uk-icon-caret-left:before { + content: "\f0d9" +} + +.uk-icon-caret-right:before { + content: "\f0da" +} + +.uk-icon-columns:before { + content: "\f0db" +} + +.uk-icon-unsorted:before, +.uk-icon-sort:before { + content: "\f0dc" +} + +.uk-icon-sort-down:before, +.uk-icon-sort-desc:before { + content: "\f0dd" +} + +.uk-icon-sort-up:before, +.uk-icon-sort-asc:before { + content: "\f0de" +} + +.uk-icon-envelope:before { + content: "\f0e0" +} + +.uk-icon-linkedin:before { + content: "\f0e1" +} + +.uk-icon-rotate-left:before, +.uk-icon-undo:before { + content: "\f0e2" +} + +.uk-icon-legal:before, +.uk-icon-gavel:before { + content: "\f0e3" +} + +.uk-icon-dashboard:before, +.uk-icon-tachometer:before { + content: "\f0e4" +} + +.uk-icon-comment-o:before { + content: "\f0e5" +} + +.uk-icon-comments-o:before { + content: "\f0e6" +} + +.uk-icon-flash:before, +.uk-icon-bolt:before { + content: "\f0e7" +} + +.uk-icon-sitemap:before { + content: "\f0e8" +} + +.uk-icon-umbrella:before { + content: "\f0e9" +} + +.uk-icon-paste:before, +.uk-icon-clipboard:before { + content: "\f0ea" +} + +.uk-icon-lightbulb-o:before { + content: "\f0eb" +} + +.uk-icon-exchange:before { + content: "\f0ec" +} + +.uk-icon-cloud-download:before { + content: "\f0ed" +} + +.uk-icon-cloud-upload:before { + content: "\f0ee" +} + +.uk-icon-user-md:before { + content: "\f0f0" +} + +.uk-icon-stethoscope:before { + content: "\f0f1" +} + +.uk-icon-suitcase:before { + content: "\f0f2" +} + +.uk-icon-bell-o:before { + content: "\f0a2" +} + +.uk-icon-coffee:before { + content: "\f0f4" +} + +.uk-icon-cutlery:before { + content: "\f0f5" +} + +.uk-icon-file-text-o:before { + content: "\f0f6" +} + +.uk-icon-building-o:before { + content: "\f0f7" +} + +.uk-icon-hospital-o:before { + content: "\f0f8" +} + +.uk-icon-ambulance:before { + content: "\f0f9" +} + +.uk-icon-medkit:before { + content: "\f0fa" +} + +.uk-icon-fighter-jet:before { + content: "\f0fb" +} + +.uk-icon-beer:before { + content: "\f0fc" +} + +.uk-icon-h-square:before { + content: "\f0fd" +} + +.uk-icon-plus-square:before { + content: "\f0fe" +} + +.uk-icon-angle-double-left:before { + content: "\f100" +} + +.uk-icon-angle-double-right:before { + content: "\f101" +} + +.uk-icon-angle-double-up:before { + content: "\f102" +} + +.uk-icon-angle-double-down:before { + content: "\f103" +} + +.uk-icon-angle-left:before { + content: "\f104" +} + +.uk-icon-angle-right:before { + content: "\f105" +} + +.uk-icon-angle-up:before { + content: "\f106" +} + +.uk-icon-angle-down:before { + content: "\f107" +} + +.uk-icon-desktop:before { + content: "\f108" +} + +.uk-icon-laptop:before { + content: "\f109" +} + +.uk-icon-tablet:before { + content: "\f10a" +} + +.uk-icon-mobile-phone:before, +.uk-icon-mobile:before { + content: "\f10b" +} + +.uk-icon-circle-o:before { + content: "\f10c" +} + +.uk-icon-quote-left:before { + content: "\f10d" +} + +.uk-icon-quote-right:before { + content: "\f10e" +} + +.uk-icon-spinner:before { + content: "\f110" +} + +.uk-icon-circle:before { + content: "\f111" +} + +.uk-icon-mail-reply:before, +.uk-icon-reply:before { + content: "\f112" +} + +.uk-icon-github-alt:before { + content: "\f113" +} + +.uk-icon-folder-o:before { + content: "\f114" +} + +.uk-icon-folder-open-o:before { + content: "\f115" +} + +.uk-icon-smile-o:before { + content: "\f118" +} + +.uk-icon-frown-o:before { + content: "\f119" +} + +.uk-icon-meh-o:before { + content: "\f11a" +} + +.uk-icon-gamepad:before { + content: "\f11b" +} + +.uk-icon-keyboard-o:before { + content: "\f11c" +} + +.uk-icon-flag-o:before { + content: "\f11d" +} + +.uk-icon-flag-checkered:before { + content: "\f11e" +} + +.uk-icon-terminal:before { + content: "\f120" +} + +.uk-icon-code:before { + content: "\f121" +} + +.uk-icon-mail-reply-all:before, +.uk-icon-reply-all:before { + content: "\f122" +} + +.uk-icon-star-half-empty:before, +.uk-icon-star-half-full:before, +.uk-icon-star-half-o:before { + content: "\f123" +} + +.uk-icon-location-arrow:before { + content: "\f124" +} + +.uk-icon-crop:before { + content: "\f125" +} + +.uk-icon-code-fork:before { + content: "\f126" +} + +.uk-icon-unlink:before, +.uk-icon-chain-broken:before { + content: "\f127" +} + +.uk-icon-question:before { + content: "\f128" +} + +.uk-icon-info:before { + content: "\f129" +} + +.uk-icon-exclamation:before { + content: "\f12a" +} + +.uk-icon-superscript:before { + content: "\f12b" +} + +.uk-icon-subscript:before { + content: "\f12c" +} + +.uk-icon-eraser:before { + content: "\f12d" +} + +.uk-icon-puzzle-piece:before { + content: "\f12e" +} + +.uk-icon-microphone:before { + content: "\f130" +} + +.uk-icon-microphone-slash:before { + content: "\f131" +} + +.uk-icon-shield:before { + content: "\f132" +} + +.uk-icon-calendar-o:before { + content: "\f133" +} + +.uk-icon-fire-extinguisher:before { + content: "\f134" +} + +.uk-icon-rocket:before { + content: "\f135" +} + +.uk-icon-maxcdn:before { + content: "\f136" +} + +.uk-icon-chevron-circle-left:before { + content: "\f137" +} + +.uk-icon-chevron-circle-right:before { + content: "\f138" +} + +.uk-icon-chevron-circle-up:before { + content: "\f139" +} + +.uk-icon-chevron-circle-down:before { + content: "\f13a" +} + +.uk-icon-html5:before { + content: "\f13b" +} + +.uk-icon-css3:before { + content: "\f13c" +} + +.uk-icon-anchor:before { + content: "\f13d" +} + +.uk-icon-unlock-alt:before { + content: "\f13e" +} + +.uk-icon-bullseye:before { + content: "\f140" +} + +.uk-icon-ellipsis-h:before { + content: "\f141" +} + +.uk-icon-ellipsis-v:before { + content: "\f142" +} + +.uk-icon-rss-square:before { + content: "\f143" +} + +.uk-icon-play-circle:before { + content: "\f144" +} + +.uk-icon-ticket:before { + content: "\f145" +} + +.uk-icon-minus-square:before { + content: "\f146" +} + +.uk-icon-minus-square-o:before { + content: "\f147" +} + +.uk-icon-level-up:before { + content: "\f148" +} + +.uk-icon-level-down:before { + content: "\f149" +} + +.uk-icon-check-square:before { + content: "\f14a" +} + +.uk-icon-pencil-square:before { + content: "\f14b" +} + +.uk-icon-external-link-square:before { + content: "\f14c" +} + +.uk-icon-share-square:before { + content: "\f14d" +} + +.uk-icon-compass:before { + content: "\f14e" +} + +.uk-icon-toggle-down:before, +.uk-icon-caret-square-o-down:before { + content: "\f150" +} + +.uk-icon-toggle-up:before, +.uk-icon-caret-square-o-up:before { + content: "\f151" +} + +.uk-icon-toggle-right:before, +.uk-icon-caret-square-o-right:before { + content: "\f152" +} + +.uk-icon-euro:before, +.uk-icon-eur:before { + content: "\f153" +} + +.uk-icon-gbp:before { + content: "\f154" +} + +.uk-icon-dollar:before, +.uk-icon-usd:before { + content: "\f155" +} + +.uk-icon-rupee:before, +.uk-icon-inr:before { + content: "\f156" +} + +.uk-icon-cny:before, +.uk-icon-rmb:before, +.uk-icon-yen:before, +.uk-icon-jpy:before { + content: "\f157" +} + +.uk-icon-ruble:before, +.uk-icon-rouble:before, +.uk-icon-rub:before { + content: "\f158" +} + +.uk-icon-won:before, +.uk-icon-krw:before { + content: "\f159" +} + +.uk-icon-bitcoin:before, +.uk-icon-btc:before { + content: "\f15a" +} + +.uk-icon-file:before { + content: "\f15b" +} + +.uk-icon-file-text:before { + content: "\f15c" +} + +.uk-icon-sort-alpha-asc:before { + content: "\f15d" +} + +.uk-icon-sort-alpha-desc:before { + content: "\f15e" +} + +.uk-icon-sort-amount-asc:before { + content: "\f160" +} + +.uk-icon-sort-amount-desc:before { + content: "\f161" +} + +.uk-icon-sort-numeric-asc:before { + content: "\f162" +} + +.uk-icon-sort-numeric-desc:before { + content: "\f163" +} + +.uk-icon-thumbs-up:before { + content: "\f164" +} + +.uk-icon-thumbs-down:before { + content: "\f165" +} + +.uk-icon-youtube-square:before { + content: "\f166" +} + +.uk-icon-youtube:before { + content: "\f167" +} + +.uk-icon-xing:before { + content: "\f168" +} + +.uk-icon-xing-square:before { + content: "\f169" +} + +.uk-icon-youtube-play:before { + content: "\f16a" +} + +.uk-icon-dropbox:before { + content: "\f16b" +} + +.uk-icon-stack-overflow:before { + content: "\f16c" +} + +.uk-icon-instagram:before { + content: "\f16d" +} + +.uk-icon-flickr:before { + content: "\f16e" +} + +.uk-icon-adn:before { + content: "\f170" +} + +.uk-icon-bitbucket:before { + content: "\f171" +} + +.uk-icon-bitbucket-square:before { + content: "\f172" +} + +.uk-icon-tumblr:before { + content: "\f173" +} + +.uk-icon-tumblr-square:before { + content: "\f174" +} + +.uk-icon-long-arrow-down:before { + content: "\f175" +} + +.uk-icon-long-arrow-up:before { + content: "\f176" +} + +.uk-icon-long-arrow-left:before { + content: "\f177" +} + +.uk-icon-long-arrow-right:before { + content: "\f178" +} + +.uk-icon-apple:before { + content: "\f179" +} + +.uk-icon-windows:before { + content: "\f17a" +} + +.uk-icon-android:before { + content: "\f17b" +} + +.uk-icon-linux:before { + content: "\f17c" +} + +.uk-icon-dribbble:before { + content: "\f17d" +} + +.uk-icon-skype:before { + content: "\f17e" +} + +.uk-icon-foursquare:before { + content: "\f180" +} + +.uk-icon-trello:before { + content: "\f181" +} + +.uk-icon-female:before { + content: "\f182" +} + +.uk-icon-male:before { + content: "\f183" +} + +.uk-icon-gittip:before, +.uk-icon-gratipay:before { + content: "\f184" +} + +.uk-icon-sun-o:before { + content: "\f185" +} + +.uk-icon-moon-o:before { + content: "\f186" +} + +.uk-icon-archive:before { + content: "\f187" +} + +.uk-icon-bug:before { + content: "\f188" +} + +.uk-icon-vk:before { + content: "\f189" +} + +.uk-icon-weibo:before { + content: "\f18a" +} + +.uk-icon-renren:before { + content: "\f18b" +} + +.uk-icon-pagelines:before { + content: "\f18c" +} + +.uk-icon-stack-exchange:before { + content: "\f18d" +} + +.uk-icon-arrow-circle-o-right:before { + content: "\f18e" +} + +.uk-icon-arrow-circle-o-left:before { + content: "\f190" +} + +.uk-icon-toggle-left:before, +.uk-icon-caret-square-o-left:before { + content: "\f191" +} + +.uk-icon-dot-circle-o:before { + content: "\f192" +} + +.uk-icon-wheelchair:before { + content: "\f193" +} + +.uk-icon-vimeo-square:before { + content: "\f194" +} + +.uk-icon-turkish-lira:before, +.uk-icon-try:before { + content: "\f195" +} + +.uk-icon-plus-square-o:before { + content: "\f196" +} + +.uk-icon-space-shuttle:before { + content: "\f197" +} + +.uk-icon-slack:before { + content: "\f198" +} + +.uk-icon-envelope-square:before { + content: "\f199" +} + +.uk-icon-wordpress:before { + content: "\f19a" +} + +.uk-icon-openid:before { + content: "\f19b" +} + +.uk-icon-institution:before, +.uk-icon-bank:before, +.uk-icon-university:before { + content: "\f19c" +} + +.uk-icon-mortar-board:before, +.uk-icon-graduation-cap:before { + content: "\f19d" +} + +.uk-icon-yahoo:before { + content: "\f19e" +} + +.uk-icon-google:before { + content: "\f1a0" +} + +.uk-icon-reddit:before { + content: "\f1a1" +} + +.uk-icon-reddit-square:before { + content: "\f1a2" +} + +.uk-icon-stumbleupon-circle:before { + content: "\f1a3" +} + +.uk-icon-stumbleupon:before { + content: "\f1a4" +} + +.uk-icon-delicious:before { + content: "\f1a5" +} + +.uk-icon-digg:before { + content: "\f1a6" +} + +.uk-icon-pied-piper:before { + content: "\f1a7" +} + +.uk-icon-pied-piper-alt:before { + content: "\f1a8" +} + +.uk-icon-drupal:before { + content: "\f1a9" +} + +.uk-icon-joomla:before { + content: "\f1aa" +} + +.uk-icon-language:before { + content: "\f1ab" +} + +.uk-icon-fax:before { + content: "\f1ac" +} + +.uk-icon-building:before { + content: "\f1ad" +} + +.uk-icon-child:before { + content: "\f1ae" +} + +.uk-icon-paw:before { + content: "\f1b0" +} + +.uk-icon-spoon:before { + content: "\f1b1" +} + +.uk-icon-cube:before { + content: "\f1b2" +} + +.uk-icon-cubes:before { + content: "\f1b3" +} + +.uk-icon-behance:before { + content: "\f1b4" +} + +.uk-icon-behance-square:before { + content: "\f1b5" +} + +.uk-icon-steam:before { + content: "\f1b6" +} + +.uk-icon-steam-square:before { + content: "\f1b7" +} + +.uk-icon-recycle:before { + content: "\f1b8" +} + +.uk-icon-automobile:before, +.uk-icon-car:before { + content: "\f1b9" +} + +.uk-icon-cab:before, +.uk-icon-taxi:before { + content: "\f1ba" +} + +.uk-icon-tree:before { + content: "\f1bb" +} + +.uk-icon-spotify:before { + content: "\f1bc" +} + +.uk-icon-deviantart:before { + content: "\f1bd" +} + +.uk-icon-soundcloud:before { + content: "\f1be" +} + +.uk-icon-database:before { + content: "\f1c0" +} + +.uk-icon-file-pdf-o:before { + content: "\f1c1" +} + +.uk-icon-file-word-o:before { + content: "\f1c2" +} + +.uk-icon-file-excel-o:before { + content: "\f1c3" +} + +.uk-icon-file-powerpoint-o:before { + content: "\f1c4" +} + +.uk-icon-file-photo-o:before, +.uk-icon-file-picture-o:before, +.uk-icon-file-image-o:before { + content: "\f1c5" +} + +.uk-icon-file-zip-o:before, +.uk-icon-file-archive-o:before { + content: "\f1c6" +} + +.uk-icon-file-sound-o:before, +.uk-icon-file-audio-o:before { + content: "\f1c7" +} + +.uk-icon-file-movie-o:before, +.uk-icon-file-video-o:before { + content: "\f1c8" +} + +.uk-icon-file-code-o:before { + content: "\f1c9" +} + +.uk-icon-vine:before { + content: "\f1ca" +} + +.uk-icon-codepen:before { + content: "\f1cb" +} + +.uk-icon-jsfiddle:before { + content: "\f1cc" +} + +.uk-icon-life-bouy:before, +.uk-icon-life-buoy:before, +.uk-icon-life-saver:before, +.uk-icon-support:before, +.uk-icon-life-ring:before { + content: "\f1cd" +} + +.uk-icon-circle-o-notch:before { + content: "\f1ce" +} + +.uk-icon-ra:before, +.uk-icon-rebel:before { + content: "\f1d0" +} + +.uk-icon-ge:before, +.uk-icon-empire:before { + content: "\f1d1" +} + +.uk-icon-git-square:before { + content: "\f1d2" +} + +.uk-icon-git:before { + content: "\f1d3" +} + +.uk-icon-hacker-news:before { + content: "\f1d4" +} + +.uk-icon-tencent-weibo:before { + content: "\f1d5" +} + +.uk-icon-qq:before { + content: "\f1d6" +} + +.uk-icon-wechat:before, +.uk-icon-weixin:before { + content: "\f1d7" +} + +.uk-icon-send:before, +.uk-icon-paper-plane:before { + content: "\f1d8" +} + +.uk-icon-send-o:before, +.uk-icon-paper-plane-o:before { + content: "\f1d9" +} + +.uk-icon-history:before { + content: "\f1da" +} + +.uk-icon-genderless:before, +.uk-icon-circle-thin:before { + content: "\f1db" +} + +.uk-icon-header:before { + content: "\f1dc" +} + +.uk-icon-paragraph:before { + content: "\f1dd" +} + +.uk-icon-sliders:before { + content: "\f1de" +} + +.uk-icon-share-alt:before { + content: "\f1e0" +} + +.uk-icon-share-alt-square:before { + content: "\f1e1" +} + +.uk-icon-bomb:before { + content: "\f1e2" +} + +.uk-icon-soccer-ball-o:before, +.uk-icon-futbol-o:before { + content: "\f1e3" +} + +.uk-icon-tty:before { + content: "\f1e4" +} + +.uk-icon-binoculars:before { + content: "\f1e5" +} + +.uk-icon-plug:before { + content: "\f1e6" +} + +.uk-icon-slideshare:before { + content: "\f1e7" +} + +.uk-icon-twitch:before { + content: "\f1e8" +} + +.uk-icon-yelp:before { + content: "\f1e9" +} + +.uk-icon-newspaper-o:before { + content: "\f1ea" +} + +.uk-icon-wifi:before { + content: "\f1eb" +} + +.uk-icon-calculator:before { + content: "\f1ec" +} + +.uk-icon-paypal:before { + content: "\f1ed" +} + +.uk-icon-google-wallet:before { + content: "\f1ee" +} + +.uk-icon-cc-visa:before { + content: "\f1f0" +} + +.uk-icon-cc-mastercard:before { + content: "\f1f1" +} + +.uk-icon-cc-discover:before { + content: "\f1f2" +} + +.uk-icon-cc-amex:before { + content: "\f1f3" +} + +.uk-icon-cc-paypal:before { + content: "\f1f4" +} + +.uk-icon-cc-stripe:before { + content: "\f1f5" +} + +.uk-icon-bell-slash:before { + content: "\f1f6" +} + +.uk-icon-bell-slash-o:before { + content: "\f1f7" +} + +.uk-icon-trash:before { + content: "\f1f8" +} + +.uk-icon-copyright:before { + content: "\f1f9" +} + +.uk-icon-at:before { + content: "\f1fa" +} + +.uk-icon-eyedropper:before { + content: "\f1fb" +} + +.uk-icon-paint-brush:before { + content: "\f1fc" +} + +.uk-icon-birthday-cake:before { + content: "\f1fd" +} + +.uk-icon-area-chart:before { + content: "\f1fe" +} + +.uk-icon-pie-chart:before { + content: "\f200" +} + +.uk-icon-line-chart:before { + content: "\f201" +} + +.uk-icon-lastfm:before { + content: "\f202" +} + +.uk-icon-lastfm-square:before { + content: "\f203" +} + +.uk-icon-toggle-off:before { + content: "\f204" +} + +.uk-icon-toggle-on:before { + content: "\f205" +} + +.uk-icon-bicycle:before { + content: "\f206" +} + +.uk-icon-bus:before { + content: "\f207" +} + +.uk-icon-ioxhost:before { + content: "\f208" +} + +.uk-icon-angellist:before { + content: "\f209" +} + +.uk-icon-cc:before { + content: "\f20a" +} + +.uk-icon-shekel:before, +.uk-icon-sheqel:before, +.uk-icon-ils:before { + content: "\f20b" +} + +.uk-icon-meanpath:before { + content: "\f20c" +} + +.uk-icon-buysellads:before { + content: "\f20d" +} + +.uk-icon-connectdevelop:before { + content: "\f20e" +} + +.uk-icon-dashcube:before { + content: "\f210" +} + +.uk-icon-forumbee:before { + content: "\f211" +} + +.uk-icon-leanpub:before { + content: "\f212" +} + +.uk-icon-sellsy:before { + content: "\f213" +} + +.uk-icon-shirtsinbulk:before { + content: "\f214" +} + +.uk-icon-simplybuilt:before { + content: "\f215" +} + +.uk-icon-skyatlas:before { + content: "\f216" +} + +.uk-icon-cart-plus:before { + content: "\f217" +} + +.uk-icon-cart-arrow-down:before { + content: "\f218" +} + +.uk-icon-diamond:before { + content: "\f219" +} + +.uk-icon-ship:before { + content: "\f21a" +} + +.uk-icon-user-secret:before { + content: "\f21b" +} + +.uk-icon-motorcycle:before { + content: "\f21c" +} + +.uk-icon-street-view:before { + content: "\f21d" +} + +.uk-icon-heartbeat:before { + content: "\f21e" +} + +.uk-icon-venus:before { + content: "\f221" +} + +.uk-icon-mars:before { + content: "\f222" +} + +.uk-icon-mercury:before { + content: "\f223" +} + +.uk-icon-transgender:before { + content: "\f224" +} + +.uk-icon-transgender-alt:before { + content: "\f225" +} + +.uk-icon-venus-double:before { + content: "\f226" +} + +.uk-icon-mars-double:before { + content: "\f227" +} + +.uk-icon-venus-mars:before { + content: "\f228" +} + +.uk-icon-mars-stroke:before { + content: "\f229" +} + +.uk-icon-mars-stroke-v:before { + content: "\f22a" +} + +.uk-icon-mars-stroke-h:before { + content: "\f22b" +} + +.uk-icon-neuter:before { + content: "\f22c" +} + +.uk-icon-facebook-official:before { + content: "\f230" +} + +.uk-icon-pinterest-p:before { + content: "\f231" +} + +.uk-icon-whatsapp:before { + content: "\f232" +} + +.uk-icon-server:before { + content: "\f233" +} + +.uk-icon-user-plus:before { + content: "\f234" +} + +.uk-icon-user-times:before { + content: "\f235" +} + +.uk-icon-hotel:before, +.uk-icon-bed:before { + content: "\f236" +} + +.uk-icon-viacoin:before { + content: "\f237" +} + +.uk-icon-train:before { + content: "\f238" +} + +.uk-icon-subway:before { + content: "\f239" +} + +.uk-icon-medium-logo:before { + content: "\f23a" +} + +.uk-icon-500px:before { + content: "\f26e" +} + +.uk-icon-amazon:before { + content: "\f270" +} + +.uk-icon-balance-scale:before { + content: "\f24e" +} + +.uk-icon-battery-empty:before, +.uk-icon-battery-0:before { + content: "\f244" +} + +.uk-icon-battery-quarter:before, +.uk-icon-battery-1:before { + content: "\f243" +} + +.uk-icon-battery-half:before, +.uk-icon-battery-2:before { + content: "\f242" +} + +.uk-icon-battery-three-quarters:before, +.uk-icon-battery-3:before { + content: "\f241" +} + +.uk-icon-battery-full:before, +.uk-icon-battery-4:before { + content: "\f240" +} + +.uk-icon-black-tie:before { + content: "\f27e" +} + +.uk-icon-calendar-check-o:before { + content: "\f274" +} + +.uk-icon-calendar-minus-o:before { + content: "\f272" +} + +.uk-icon-calendar-plus-o:before { + content: "\f271" +} + +.uk-icon-calendar-times-o:before { + content: "\f273" +} + +.uk-icon-cc-diners-club:before { + content: "\f24c" +} + +.uk-icon-cc-jcb:before { + content: "\f24b" +} + +.uk-icon-chrome:before { + content: "\f268" +} + +.uk-icon-clone:before { + content: "\f24d" +} + +.uk-icon-commenting:before { + content: "\f27a" +} + +.uk-icon-commenting-o:before { + content: "\f27b" +} + +.uk-icon-contao:before { + content: "\f26d" +} + +.uk-icon-creative-commons:before { + content: "\f25e" +} + +.uk-icon-expeditedssl:before { + content: "\f23e" +} + +.uk-icon-firefox:before { + content: "\f269" +} + +.uk-icon-fonticons:before { + content: "\f280" +} + +.uk-icon-get-pocket:before { + content: "\f265" +} + +.uk-icon-gg:before { + content: "\f260" +} + +.uk-icon-gg-circle:before { + content: "\f261" +} + +.uk-icon-hand-lizard-o:before { + content: "\f258" +} + +.uk-icon-hand-stop-o:before, +.uk-icon-hand-paper-o:before { + content: "\f256" +} + +.uk-icon-hand-peace-o:before { + content: "\f25b" +} + +.uk-icon-hand-pointer-o:before { + content: "\f25a" +} + +.uk-icon-hand-grab-o:before, +.uk-icon-hand-rock-o:before { + content: "\f255" +} + +.uk-icon-hand-scissors-o:before { + content: "\f257" +} + +.uk-icon-hand-spock-o:before { + content: "\f259" +} + +.uk-icon-hourglass:before { + content: "\f254" +} + +.uk-icon-hourglass-o:before { + content: "\f250" +} + +.uk-icon-hourglass-1:before, +.uk-icon-hourglass-start:before { + content: "\f251" +} + +.uk-icon-hourglass-2:before, +.uk-icon-hourglass-half:before { + content: "\f252" +} + +.uk-icon-hourglass-3:before, +.uk-icon-hourglass-end:before { + content: "\f253" +} + +.uk-icon-houzz:before { + content: "\f27c" +} + +.uk-icon-i-cursor:before { + content: "\f246" +} + +.uk-icon-industry:before { + content: "\f275" +} + +.uk-icon-internet-explorer:before { + content: "\f26b" +} + +.uk-icon-map:before { + content: "\f279" +} + +.uk-icon-map-o:before { + content: "\f278" +} + +.uk-icon-map-pin:before { + content: "\f276" +} + +.uk-icon-map-signs:before { + content: "\f277" +} + +.uk-icon-mouse-pointer:before { + content: "\f245" +} + +.uk-icon-object-group:before { + content: "\f247" +} + +.uk-icon-object-ungroup:before { + content: "\f248" +} + +.uk-icon-odnoklassniki:before { + content: "\f263" +} + +.uk-icon-odnoklassniki-square:before { + content: "\f264" +} + +.uk-icon-opencart:before { + content: "\f23d" +} + +.uk-icon-opera:before { + content: "\f26a" +} + +.uk-icon-optin-monster:before { + content: "\f23c" +} + +.uk-icon-registered:before { + content: "\f25d" +} + +.uk-icon-safari:before { + content: "\f267" +} + +.uk-icon-sticky-note:before { + content: "\f249" +} + +.uk-icon-sticky-note-o:before { + content: "\f24a" +} + +.uk-icon-tv:before, +.uk-icon-television:before { + content: "\f26c" +} + +.uk-icon-trademark:before { + content: "\f25c" +} + +.uk-icon-tripadvisor:before { + content: "\f262" +} + +.uk-icon-vimeo:before { + content: "\f27d" +} + +.uk-icon-wikipedia-w:before { + content: "\f266" +} + +.uk-icon-yc:before, +.uk-icon-y-combinator:before { + content: "\f23b" +} + +.uk-icon-yc-square:before, +.uk-icon-y-combinator-square:before { + content: "\f1d4" +} + +.uk-icon-bluetooth:before { + content: "\f293" +} + +.uk-icon-bluetooth-b:before { + content: "\f294" +} + +.uk-icon-codiepie:before { + content: "\f284" +} + +.uk-icon-credit-card-alt:before { + content: "\f283" +} + +.uk-icon-edge:before { + content: "\f282" +} + +.uk-icon-fort-awesome:before { + content: "\f286" +} + +.uk-icon-hashtag:before { + content: "\f292" +} + +.uk-icon-mixcloud:before { + content: "\f289" +} + +.uk-icon-modx:before { + content: "\f285" +} + +.uk-icon-pause-circle:before { + content: "\f28b" +} + +.uk-icon-pause-circle-o:before { + content: "\f28c" +} + +.uk-icon-percent:before { + content: "\f295" +} + +.uk-icon-product-hunt:before { + content: "\f288" +} + +.uk-icon-reddit-alien:before { + content: "\f281" +} + +.uk-icon-scribd:before { + content: "\f28a" +} + +.uk-icon-shopping-bag:before { + content: "\f290" +} + +.uk-icon-shopping-basket:before { + content: "\f291" +} + +.uk-icon-stop-circle:before { + content: "\f28d" +} + +.uk-icon-stop-circle-o:before { + content: "\f28e" +} + +.uk-icon-usb:before { + content: "\f287" +} + +.uk-close::-moz-focus-inner { + border: 0; + padding: 0 +} + +.uk-close { + -webkit-appearance: none; + margin: 0; + border: none; + overflow: visible; + font: inherit; + color: inherit; + text-transform: none; + padding: 0; + background: transparent; + display: inline-block; + box-sizing: content-box; + width: 20px; + line-height: 20px; + text-align: center; + vertical-align: middle; + opacity: 0.3 +} + +.uk-close:after { + display: block; + content: "\f00d"; + font-family: FontAwesome +} + +.uk-close:hover, +.uk-close:focus { + opacity: 0.5; + outline: none; + color: inherit; + text-decoration: none; + cursor: pointer +} + +.uk-close-alt { + padding: 2px; + border-radius: 50%; + background: #fff; + opacity: 1; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 0 6px rgba(0, 0, 0, 0.3) +} + +.uk-close-alt:hover, +.uk-close-alt:focus { + opacity: 1 +} + +.uk-close-alt:after { + opacity: 0.5 +} + +.uk-close-alt:hover:after, +.uk-close-alt:focus:after { + opacity: 0.8 +} + +.uk-badge { + display: inline-block; + padding: 0 5px; + background: #009dd8; + font-size: 10px; + font-weight: bold; + line-height: 14px; + color: #fff; + text-align: center; + vertical-align: middle; + text-transform: none; + border: 1px solid rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.3); + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #00b4f5, #008dc5); + background-image: linear-gradient(to bottom, #00b4f5, #008dc5); + border-radius: 2px; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +a.uk-badge:hover { + color: #fff +} + +.uk-badge-notification { + box-sizing: border-box; + min-width: 18px; + border-radius: 500px; + font-size: 12px; + line-height: 18px +} + +.uk-badge-success { + background-color: #82bb42; + background-image: -webkit-linear-gradient(top, #9fd256, #6fac34); + background-image: linear-gradient(to bottom, #9fd256, #6fac34) +} + +.uk-badge-warning { + background-color: #f9a124; + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406) +} + +.uk-badge-danger { + background-color: #d32c46; + background-image: -webkit-linear-gradient(top, #ee465a, #c11a39); + background-image: linear-gradient(to bottom, #ee465a, #c11a39) +} + +.uk-alert { + margin-bottom: 15px; + padding: 10px; + background: #ebf7fd; + color: #2d7091; + border: 1px solid rgba(45, 112, 145, 0.3); + border-radius: 4px; + text-shadow: 0 1px 0 #fff +} + +*+.uk-alert { + margin-top: 15px +} + +.uk-alert>:last-child { + margin-bottom: 0 +} + +.uk-alert h1, +.uk-alert h2, +.uk-alert h3, +.uk-alert h4, +.uk-alert h5, +.uk-alert h6 { + color: inherit +} + +.uk-alert>.uk-close:first-child { + float: right +} + +.uk-alert>.uk-close:first-child+* { + margin-top: 0 +} + +.uk-alert-success { + background: #f2fae3; + color: #659f13; + border-color: rgba(101, 159, 19, 0.3) +} + +.uk-alert-warning { + background: #fffceb; + color: #e28327; + border-color: rgba(226, 131, 39, 0.3) +} + +.uk-alert-danger { + background: #fff1f0; + color: #d85030; + border-color: rgba(216, 80, 48, 0.3) +} + +.uk-alert-large { + padding: 20px +} + +.uk-alert-large>.uk-close:first-child { + margin: -10px -10px 0 0 +} + +.uk-thumbnail { + display: inline-block; + max-width: 100%; + box-sizing: border-box; + margin: 0; + padding: 4px; + border: 1px solid #ddd; + background: #fff; + border-radius: 4px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) +} + +a.uk-thumbnail:hover, +a.uk-thumbnail:focus { + border-color: #aaa; + background-color: #fff; + text-decoration: none; + outline: none; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3) +} + +.uk-thumbnail-caption { + padding-top: 4px; + text-align: center; + color: #444 +} + +.uk-thumbnail-mini { + width: 150px +} + +.uk-thumbnail-small { + width: 200px +} + +.uk-thumbnail-medium { + width: 300px +} + +.uk-thumbnail-large { + width: 400px +} + +.uk-thumbnail-expand, +.uk-thumbnail-expand>img { + width: 100% +} + +.uk-overlay { + display: inline-block; + position: relative; + max-width: 100%; + vertical-align: middle; + overflow: hidden; + -webkit-transform: translateZ(0); + margin: 0 +} + +.uk-overlay.uk-border-circle { + -webkit-mask-image: -webkit-radial-gradient(circle, #fff 100%, #000 100%) +} + +.uk-overlay>:first-child { + margin-bottom: 0 +} + +.uk-overlay-panel { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: 20px; + color: #fff +} + +.uk-overlay-panel>:last-child, +.uk-overlay-panel.uk-flex>*>:last-child { + margin-bottom: 0 +} + +.uk-overlay-panel h1, +.uk-overlay-panel h2, +.uk-overlay-panel h3, +.uk-overlay-panel h4, +.uk-overlay-panel h5, +.uk-overlay-panel h6 { + color: inherit +} + +.uk-overlay-panel a:not([class]) { + color: inherit; + text-decoration: underline +} + +.uk-overlay-panel a[class*='uk-icon-']:not(.uk-icon-button) { + color: inherit +} + +.uk-overlay-hover:not(:hover):not(.uk-hover) .uk-overlay-panel:not(.uk-ignore) { + opacity: 0 +} + +.uk-overlay-active:not(.uk-active)>.uk-overlay-panel:not(.uk-ignore) { + opacity: 0 +} + +.uk-overlay-background { + background: rgba(0, 0, 0, 0.5) +} + +.uk-overlay-image { + padding: 0 +} + +.uk-overlay-top { + bottom: auto +} + +.uk-overlay-bottom { + top: auto +} + +.uk-overlay-left { + right: auto +} + +.uk-overlay-right { + left: auto +} + +.uk-overlay-icon:before { + content: "\f002"; + position: absolute; + top: 50%; + left: 50%; + width: 50px; + height: 50px; + margin-top: -25px; + margin-left: -25px; + font-size: 50px; + line-height: 1; + font-family: FontAwesome; + text-align: center; + color: #fff +} + +.uk-overlay-fade, +.uk-overlay-scale, +.uk-overlay-spin, +.uk-overlay-grayscale, +.uk-overlay-blur, +[class*='uk-overlay-slide'] { + transition-duration: 0.3s; + transition-timing-function: ease-out; + transition-property: opacity, transform, filter +} + +.uk-overlay-active .uk-overlay-fade, +.uk-overlay-active .uk-overlay-scale, +.uk-overlay-active .uk-overlay-spin, +.uk-overlay-active [class*='uk-overlay-slide'] { + transition-duration: 0.8s +} + +.uk-overlay-fade { + opacity: .7 +} + +.uk-overlay-hover:hover .uk-overlay-fade, +.uk-overlay-hover.uk-hover .uk-overlay-fade, +.uk-overlay-active .uk-active>.uk-overlay-fade { + opacity: 1 +} + +.uk-overlay-scale { + -webkit-transform: scale(1); + transform: scale(1) +} + +.uk-overlay-hover:hover .uk-overlay-scale, +.uk-overlay-hover.uk-hover .uk-overlay-scale, +.uk-overlay-active .uk-active>.uk-overlay-scale { + -webkit-transform: scale(1.1); + transform: scale(1.1) +} + +.uk-overlay-spin { + -webkit-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg) +} + +.uk-overlay-hover:hover .uk-overlay-spin, +.uk-overlay-hover.uk-hover .uk-overlay-spin, +.uk-overlay-active .uk-active>.uk-overlay-spin { + -webkit-transform: scale(1.1) rotate(3deg); + transform: scale(1.1) rotate(3deg) +} + +.uk-overlay-grayscale { + -webkit-filter: grayscale(100%); + filter: grayscale(100%) +} + +.uk-overlay-hover:hover .uk-overlay-grayscale, +.uk-overlay-hover.uk-hover .uk-overlay-grayscale, +.uk-overlay-active .uk-active>.uk-overlay-grayscale { + -webkit-filter: grayscale(0); + filter: grayscale(0) +} + +[class*='uk-overlay-slide'] { + opacity: 0 +} + +.uk-overlay-slide-top { + -webkit-transform: translateY(-100%); + transform: translateY(-100%) +} + +.uk-overlay-slide-bottom { + -webkit-transform: translateY(100%); + transform: translateY(100%) +} + +.uk-overlay-slide-left { + -webkit-transform: translateX(-100%); + transform: translateX(-100%) +} + +.uk-overlay-slide-right { + -webkit-transform: translateX(100%); + transform: translateX(100%) +} + +.uk-overlay-hover:hover [class*='uk-overlay-slide'], +.uk-overlay-hover.uk-hover [class*='uk-overlay-slide'], +.uk-overlay-active .uk-active>[class*='uk-overlay-slide'] { + opacity: 1; + -webkit-transform: translateX(0) translateY(0); + transform: translateX(0) translateY(0) +} + +.uk-overlay-area { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.3); + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; + -webkit-transform: translate3d(0, 0, 0) +} + +.uk-overlay:hover .uk-overlay-area, +.uk-overlay.uk-hover .uk-overlay-area, +.uk-overlay-toggle:hover .uk-overlay-area, +.uk-overlay-toggle.uk-hover .uk-overlay-area { + opacity: 1 +} + +.uk-overlay-area:empty:before { + content: "\f002"; + position: absolute; + top: 50%; + left: 50%; + width: 50px; + height: 50px; + margin-top: -25px; + margin-left: -25px; + font-size: 50px; + line-height: 1; + font-family: FontAwesome; + text-align: center; + color: #fff +} + +.uk-overlay-area:not(:empty) { + font-size: 0.001px +} + +.uk-overlay-area:not(:empty):before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: middle +} + +.uk-overlay-area-content { + display: inline-block; + box-sizing: border-box; + width: 100%; + vertical-align: middle; + font-size: 1rem; + text-align: center; + padding: 0 15px; + color: #fff +} + +.uk-overlay-area-content>:last-child { + margin-bottom: 0 +} + +.uk-overlay-area-content a:not([class]), +.uk-overlay-area-content a:not([class]):hover { + color: inherit +} + +.uk-overlay-caption { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 15px; + background: rgba(0, 0, 0, 0.5); + color: #fff; + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; + -webkit-transform: translate3d(0, 0, 0) +} + +.uk-overlay:hover .uk-overlay-caption, +.uk-overlay.uk-hover .uk-overlay-caption, +.uk-overlay-toggle:hover .uk-overlay-caption, +.uk-overlay-toggle.uk-hover .uk-overlay-caption { + opacity: 1 +} + +[class*='uk-column-'] { + -webkit-column-gap: 25px; + -moz-column-gap: 25px; + column-gap: 25px +} + +.uk-column-1-2 { + -webkit-column-count: 2; + -moz-column-count: 2; + column-count: 2 +} + +.uk-column-1-3 { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3 +} + +.uk-column-1-4 { + -webkit-column-count: 4; + -moz-column-count: 4; + column-count: 4 +} + +.uk-column-1-5 { + -webkit-column-count: 5; + -moz-column-count: 5; + column-count: 5 +} + +.uk-column-1-6 { + -webkit-column-count: 6; + -moz-column-count: 6; + column-count: 6 +} + +@media (min-width:480px) { + .uk-column-small-1-2 { + -webkit-column-count: 2; + -moz-column-count: 2; + column-count: 2 + } + .uk-column-small-1-3 { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3 + } + .uk-column-small-1-4 { + -webkit-column-count: 4; + -moz-column-count: 4; + column-count: 4 + } + .uk-column-small-1-5 { + -webkit-column-count: 5; + -moz-column-count: 5; + column-count: 5 + } + .uk-column-small-1-6 { + -webkit-column-count: 6; + -moz-column-count: 6; + column-count: 6 + } +} + +@media (min-width:768px) { + .uk-column-medium-1-2 { + -webkit-column-count: 2; + -moz-column-count: 2; + column-count: 2 + } + .uk-column-medium-1-3 { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3 + } + .uk-column-medium-1-4 { + -webkit-column-count: 4; + -moz-column-count: 4; + column-count: 4 + } + .uk-column-medium-1-5 { + -webkit-column-count: 5; + -moz-column-count: 5; + column-count: 5 + } + .uk-column-medium-1-6 { + -webkit-column-count: 6; + -moz-column-count: 6; + column-count: 6 + } +} + +@media (min-width:960px) { + .uk-column-large-1-2 { + -webkit-column-count: 2; + -moz-column-count: 2; + column-count: 2 + } + .uk-column-large-1-3 { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3 + } + .uk-column-large-1-4 { + -webkit-column-count: 4; + -moz-column-count: 4; + column-count: 4 + } + .uk-column-large-1-5 { + -webkit-column-count: 5; + -moz-column-count: 5; + column-count: 5 + } + .uk-column-large-1-6 { + -webkit-column-count: 6; + -moz-column-count: 6; + column-count: 6 + } +} + +@media (min-width:1220px) { + .uk-column-xlarge-1-2 { + -webkit-column-count: 2; + -moz-column-count: 2; + column-count: 2 + } + .uk-column-xlarge-1-3 { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3 + } + .uk-column-xlarge-1-4 { + -webkit-column-count: 4; + -moz-column-count: 4; + column-count: 4 + } + .uk-column-xlarge-1-5 { + -webkit-column-count: 5; + -moz-column-count: 5; + column-count: 5 + } + .uk-column-xlarge-1-6 { + -webkit-column-count: 6; + -moz-column-count: 6; + column-count: 6 + } +} + +[class*='uk-animation-'] { + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; + -webkit-animation-timing-function: ease-out; + animation-timing-function: ease-out; + -webkit-animation-fill-mode: both; + animation-fill-mode: both +} + +@media screen { + [data-uk-scrollspy*='uk-animation-']:not([data-uk-scrollspy*='target']) { + opacity: 0 + } +} + +.uk-animation-fade { + -webkit-animation-name: uk-fade; + animation-name: uk-fade; + -webkit-animation-duration: 0.8s; + animation-duration: 0.8s; + -webkit-animation-timing-function: linear !important; + animation-timing-function: linear !important +} + +.uk-animation-scale-up { + -webkit-animation-name: uk-fade-scale-02; + animation-name: uk-fade-scale-02 +} + +.uk-animation-scale-down { + -webkit-animation-name: uk-fade-scale-18; + animation-name: uk-fade-scale-18 +} + +.uk-animation-slide-top { + -webkit-animation-name: uk-fade-top; + animation-name: uk-fade-top +} + +.uk-animation-slide-bottom { + -webkit-animation-name: uk-fade-bottom; + animation-name: uk-fade-bottom +} + +.uk-animation-slide-left { + -webkit-animation-name: uk-fade-left; + animation-name: uk-fade-left +} + +.uk-animation-slide-right { + -webkit-animation-name: uk-fade-right; + animation-name: uk-fade-right +} + +.uk-animation-scale { + -webkit-animation-name: uk-scale-12; + animation-name: uk-scale-12 +} + +.uk-animation-shake { + -webkit-animation-name: uk-shake; + animation-name: uk-shake +} + +.uk-animation-reverse { + -webkit-animation-direction: reverse; + animation-direction: reverse; + -webkit-animation-timing-function: ease-in; + animation-timing-function: ease-in +} + +.uk-animation-15 { + -webkit-animation-duration: 15s; + animation-duration: 15s +} + +.uk-animation-top-left { + -webkit-transform-origin: 0 0; + transform-origin: 0 0 +} + +.uk-animation-top-center { + -webkit-transform-origin: 50% 0; + transform-origin: 50% 0 +} + +.uk-animation-top-right { + -webkit-transform-origin: 100% 0; + transform-origin: 100% 0 +} + +.uk-animation-middle-left { + -webkit-transform-origin: 0 50%; + transform-origin: 0 50% +} + +.uk-animation-middle-right { + -webkit-transform-origin: 100% 50%; + transform-origin: 100% 50% +} + +.uk-animation-bottom-left { + -webkit-transform-origin: 0 100%; + transform-origin: 0 100% +} + +.uk-animation-bottom-center { + -webkit-transform-origin: 50% 100%; + transform-origin: 50% 100% +} + +.uk-animation-bottom-right { + -webkit-transform-origin: 100% 100%; + transform-origin: 100% 100% +} + +.uk-animation-hover:not(:hover), +.uk-animation-hover:not(:hover) [class*='uk-animation-'], +.uk-touch .uk-animation-hover:not(.uk-hover), +.uk-touch .uk-animation-hover:not(.uk-hover) [class*='uk-animation-'] { + -webkit-animation-name: none; + animation-name: none +} + +@-webkit-keyframes uk-fade { + 0% { + opacity: 0 + } + 100% { + opacity: 1 + } +} + +@keyframes uk-fade { + 0% { + opacity: 0 + } + 100% { + opacity: 1 + } +} + +@-webkit-keyframes uk-fade-top { + 0% { + opacity: 0; + -webkit-transform: translateY(-100%) + } + 100% { + opacity: 1; + -webkit-transform: translateY(0) + } +} + +@keyframes uk-fade-top { + 0% { + opacity: 0; + transform: translateY(-100%) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +@-webkit-keyframes uk-fade-bottom { + 0% { + opacity: 0; + -webkit-transform: translateY(100%) + } + 100% { + opacity: 1; + -webkit-transform: translateY(0) + } +} + +@keyframes uk-fade-bottom { + 0% { + opacity: 0; + transform: translateY(100%) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +@-webkit-keyframes uk-fade-left { + 0% { + opacity: 0; + -webkit-transform: translateX(-100%) + } + 100% { + opacity: 1; + -webkit-transform: translateX(0) + } +} + +@keyframes uk-fade-left { + 0% { + opacity: 0; + transform: translateX(-100%) + } + 100% { + opacity: 1; + transform: translateX(0) + } +} + +@-webkit-keyframes uk-fade-right { + 0% { + opacity: 0; + -webkit-transform: translateX(100%) + } + 100% { + opacity: 1; + -webkit-transform: translateX(0) + } +} + +@keyframes uk-fade-right { + 0% { + opacity: 0; + transform: translateX(100%) + } + 100% { + opacity: 1; + transform: translateX(0) + } +} + +@-webkit-keyframes uk-fade-scale-02 { + 0% { + opacity: 0; + -webkit-transform: scale(.2) + } + 100% { + opacity: 1; + -webkit-transform: scale(1) + } +} + +@keyframes uk-fade-scale-02 { + 0% { + opacity: 0; + transform: scale(.2) + } + 100% { + opacity: 1; + transform: scale(1) + } +} + +@-webkit-keyframes uk-fade-scale-15 { + 0% { + opacity: 0; + -webkit-transform: scale(1.5) + } + 100% { + opacity: 1; + -webkit-transform: scale(1) + } +} + +@keyframes uk-fade-scale-15 { + 0% { + opacity: 0; + transform: scale(1.5) + } + 100% { + opacity: 1; + transform: scale(1) + } +} + +@-webkit-keyframes uk-fade-scale-18 { + 0% { + opacity: 0; + -webkit-transform: scale(1.8) + } + 100% { + opacity: 1; + -webkit-transform: scale(1) + } +} + +@keyframes uk-fade-scale-18 { + 0% { + opacity: 0; + transform: scale(1.8) + } + 100% { + opacity: 1; + transform: scale(1) + } +} + +@-webkit-keyframes uk-slide-left { + 0% { + -webkit-transform: translateX(-100%) + } + 100% { + -webkit-transform: translateX(0) + } +} + +@keyframes uk-slide-left { + 0% { + transform: translateX(-100%) + } + 100% { + transform: translateX(0) + } +} + +@-webkit-keyframes uk-slide-right { + 0% { + -webkit-transform: translateX(100%) + } + 100% { + -webkit-transform: translateX(0) + } +} + +@keyframes uk-slide-right { + 0% { + transform: translateX(100%) + } + 100% { + transform: translateX(0) + } +} + +@-webkit-keyframes uk-slide-left-33 { + 0% { + -webkit-transform: translateX(33%) + } + 100% { + -webkit-transform: translateX(0) + } +} + +@keyframes uk-slide-left-33 { + 0% { + transform: translateX(33%) + } + 100% { + transform: translateX(0) + } +} + +@-webkit-keyframes uk-slide-right-33 { + 0% { + -webkit-transform: translateX(-33%) + } + 100% { + -webkit-transform: translateX(0) + } +} + +@keyframes uk-slide-right-33 { + 0% { + transform: translateX(-33%) + } + 100% { + transform: translateX(0) + } +} + +@-webkit-keyframes uk-scale-12 { + 0% { + -webkit-transform: scale(1.2) + } + 100% { + -webkit-transform: scale(1) + } +} + +@keyframes uk-scale-12 { + 0% { + transform: scale(1.2) + } + 100% { + transform: scale(1) + } +} + +@-webkit-keyframes uk-rotate { + 0% { + -webkit-transform: rotate(0deg) + } + 100% { + -webkit-transform: rotate(359deg) + } +} + +@keyframes uk-rotate { + 0% { + transform: rotate(0deg) + } + 100% { + transform: rotate(359deg) + } +} + +@-webkit-keyframes uk-shake { + 0%, + 100% { + -webkit-transform: translateX(0) + } + 10% { + -webkit-transform: translateX(-9px) + } + 20% { + -webkit-transform: translateX(8px) + } + 30% { + -webkit-transform: translateX(-7px) + } + 40% { + -webkit-transform: translateX(6px) + } + 50% { + -webkit-transform: translateX(-5px) + } + 60% { + -webkit-transform: translateX(4px) + } + 70% { + -webkit-transform: translateX(-3px) + } + 80% { + -webkit-transform: translateX(2px) + } + 90% { + -webkit-transform: translateX(-1px) + } +} + +@keyframes uk-shake { + 0%, + 100% { + transform: translateX(0) + } + 10% { + transform: translateX(-9px) + } + 20% { + transform: translateX(8px) + } + 30% { + transform: translateX(-7px) + } + 40% { + transform: translateX(6px) + } + 50% { + transform: translateX(-5px) + } + 60% { + transform: translateX(4px) + } + 70% { + transform: translateX(-3px) + } + 80% { + transform: translateX(2px) + } + 90% { + transform: translateX(-1px) + } +} + +@-webkit-keyframes uk-slide-top-fixed { + 0% { + opacity: 0; + -webkit-transform: translateY(-10px) + } + 100% { + opacity: 1; + -webkit-transform: translateY(0) + } +} + +@keyframes uk-slide-top-fixed { + 0% { + opacity: 0; + transform: translateY(-10px) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +@-webkit-keyframes uk-slide-bottom-fixed { + 0% { + opacity: 0; + -webkit-transform: translateY(10px) + } + 100% { + opacity: 1; + -webkit-transform: translateY(0) + } +} + +@keyframes uk-slide-bottom-fixed { + 0% { + opacity: 0; + transform: translateY(10px) + } + 100% { + opacity: 1; + transform: translateY(0) + } +} + +.uk-dropdown, +.uk-dropdown-blank { + display: none; + position: absolute; + z-index: 1020; + box-sizing: border-box; + width: 200px +} + +.uk-dropdown { + padding: 15px; + background: #fff; + color: #444; + font-size: 1rem; + vertical-align: top; + border: 1px solid #cbcbcb; + border-radius: 4px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1) +} + +.uk-open>.uk-dropdown, +.uk-open>.uk-dropdown-blank { + display: block; + -webkit-animation: uk-fade .2s ease-in-out; + animation: uk-fade .2s ease-in-out; + -webkit-transform-origin: 0 0; + transform-origin: 0 0 +} + +.uk-dropdown-top { + margin-top: -5px +} + +.uk-dropdown-bottom { + margin-top: 5px +} + +.uk-dropdown-left { + margin-left: -5px +} + +.uk-dropdown-right { + margin-left: 5px +} + +.uk-dropdown .uk-nav { + margin: 0 -15px +} + +.uk-grid .uk-dropdown-grid+.uk-dropdown-grid { + margin-top: 15px +} + +.uk-dropdown-grid>[class*='uk-width-']>.uk-panel+.uk-panel { + margin-top: 15px +} + +@media (min-width:768px) { + .uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid { + margin-left: -15px; + margin-right: -15px + } + .uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid>[class*='uk-width-'] { + padding-left: 15px; + padding-right: 15px + } + .uk-dropdown:not(.uk-dropdown-stack)>.uk-dropdown-grid>[class*='uk-width-']:nth-child(n+2) { + border-left: 1px solid #ddd + } + .uk-dropdown-width-2:not(.uk-dropdown-stack) { + width: 400px + } + .uk-dropdown-width-3:not(.uk-dropdown-stack) { + width: 600px + } + .uk-dropdown-width-4:not(.uk-dropdown-stack) { + width: 800px + } + .uk-dropdown-width-5:not(.uk-dropdown-stack) { + width: 1000px + } +} + +@media (max-width:767px) { + .uk-dropdown-grid>[class*='uk-width-'] { + width: 100% + } + .uk-dropdown-grid>[class*='uk-width-']:nth-child(n+2) { + margin-top: 15px + } +} + +.uk-dropdown-stack>.uk-dropdown-grid>[class*='uk-width-'] { + width: 100% +} + +.uk-dropdown-stack>.uk-dropdown-grid>[class*='uk-width-']:nth-child(n+2) { + margin-top: 15px +} + +.uk-dropdown-small { + min-width: 150px; + width: auto; + padding: 5px; + white-space: nowrap +} + +.uk-dropdown-small .uk-nav { + margin: 0 -5px +} + +.uk-dropdown-navbar { + margin-top: 6px; + background: #fff; + color: #444; + left: -1px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1) +} + +.uk-open>.uk-dropdown-navbar { + -webkit-animation: uk-slide-top-fixed .2s ease-in-out; + animation: uk-slide-top-fixed .2s ease-in-out +} + +.uk-dropdown-scrollable { + overflow-y: auto; + max-height: 200px +} + +.uk-dropdown-navbar.uk-dropdown-flip { + left: auto +} + +.uk-modal { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1010; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + background: rgba(0, 0, 0, 0.6); + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; + touch-action: cross-slide-y pinch-zoom double-tap-zoom; + -webkit-transform: translateZ(0); + transform: translateZ(0) +} + +.uk-modal.uk-open { + opacity: 1 +} + +.uk-modal-page, +.uk-modal-page body { + overflow: hidden +} + +.uk-modal-dialog { + position: relative; + box-sizing: border-box; + margin: 50px auto; + padding: 20px; + width: 600px; + max-width: 100%; + max-width: calc(100% - 20px); + background: #fff; + opacity: 0; + -webkit-transform: translateY(-100px); + transform: translateY(-100px); + -webkit-transition: opacity .3s linear, -webkit-transform .3s ease-out; + transition: opacity .3s linear, transform .3s ease-out; + border-radius: 4px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3) +} + +@media (max-width:767px) { + .uk-modal-dialog { + width: auto; + margin: 10px auto + } +} + +.uk-open .uk-modal-dialog { + opacity: 1; + -webkit-transform: translateY(0); + transform: translateY(0) +} + +.uk-modal-dialog>:not([class*='uk-modal-']):last-child { + margin-bottom: 0 +} + +.uk-modal-dialog>.uk-close:first-child { + margin: -10px -10px 0 0; + float: right +} + +.uk-modal-dialog>.uk-close:first-child+:not([class*='uk-modal-']) { + margin-top: 0 +} + +.uk-modal-dialog-lightbox { + margin: 15px auto; + padding: 0; + max-width: 95%; + max-width: calc(100% - 30px); + border-radius: 0 +} + +.uk-modal-dialog-lightbox>.uk-close:first-child { + position: absolute; + top: -12px; + right: -12px; + margin: 0; + float: none +} + +@media (max-width:767px) { + .uk-modal-dialog-lightbox>.uk-close:first-child { + top: -7px; + right: -7px + } +} + +.uk-modal-dialog-blank { + margin: 0; + padding: 0; + width: 100%; + max-width: 100%; + -webkit-transition: opacity 0.3s linear; + transition: opacity 0.3s linear +} + +.uk-modal-dialog-blank>.uk-close:first-child { + position: absolute; + top: 20px; + right: 20px; + z-index: 1; + margin: 0; + float: none +} + +@media (min-width:768px) { + .uk-modal-dialog-large { + width: 930px + } +} + +@media (min-width:1220px) { + .uk-modal-dialog-large { + width: 1130px + } +} + +.uk-modal-header { + margin-bottom: 15px; + margin: -20px -20px 15px -20px; + padding: 20px; + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + background: #fafafa +} + +.uk-modal-footer { + margin-top: 15px; + margin: 15px -20px -20px -20px; + padding: 20px; + border-top: 1px solid #ddd; + border-radius: 0 0 4px 4px; + background: #fafafa +} + +.uk-modal-header>:last-child, +.uk-modal-footer>:last-child { + margin-bottom: 0 +} + +.uk-modal-caption { + position: absolute; + left: 0; + right: 0; + bottom: -20px; + margin-bottom: -10px; + color: #fff; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.uk-modal-spinner { + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + font-size: 25px; + color: #ddd +} + +.uk-modal-spinner:after { + content: "\f110"; + font-family: FontAwesome; + -webkit-animation: uk-rotate 2s infinite linear; + animation: uk-rotate 2s infinite linear +} + +.uk-offcanvas { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1000; + touch-action: none; + background: rgba(0, 0, 0, 0.1) +} + +.uk-offcanvas.uk-active { + display: block +} + +.uk-offcanvas-page { + position: fixed; + -webkit-transition: margin-left .3s ease-in-out; + transition: margin-left .3s ease-in-out +} + +.uk-offcanvas-bar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + z-index: 1001; + width: 270px; + max-width: 100%; + background: #333; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + -webkit-transition: -webkit-transform .3s ease-in-out; + transition: transform .3s ease-in-out; + -ms-scroll-chaining: none +} + +.uk-offcanvas.uk-active .uk-offcanvas-bar.uk-offcanvas-bar-show { + -webkit-transform: translateX(0); + transform: translateX(0) +} + +.uk-offcanvas-bar-flip { + left: auto; + right: 0; + -webkit-transform: translateX(100%); + transform: translateX(100%) +} + +.uk-offcanvas .uk-panel { + margin: 20px 15px; + color: #777; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5) +} + +.uk-offcanvas .uk-panel-title { + color: #ccc +} + +.uk-offcanvas .uk-panel a:not([class]) { + color: #ccc +} + +.uk-offcanvas .uk-panel a:not([class]):hover { + color: #fff +} + +.uk-offcanvas-bar:after { + content: ""; + display: block; + position: absolute; + top: 0; + bottom: 0; + right: 0; + width: 1px; + background: rgba(0, 0, 0, 0.6); + box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.6) +} + +.uk-offcanvas-bar-flip:after { + right: auto; + left: 0; + width: 1px; + background: rgba(0, 0, 0, 0.6); + box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.6) +} + +.uk-switcher { + margin: 0; + padding: 0; + list-style: none; + touch-action: cross-slide-y pinch-zoom double-tap-zoom +} + +.uk-switcher>:not(.uk-active) { + display: none +} + +.uk-text-small { + font-size: 11px; + line-height: 16px +} + +.uk-text-large { + font-size: 18px; + line-height: 24px; + font-weight: normal +} + +.uk-text-bold { + font-weight: bold +} + +.uk-text-muted { + color: #999 !important +} + +.uk-text-primary { + color: #2d7091 !important +} + +.uk-text-success { + color: #659f13 !important +} + +.uk-text-warning { + color: #e28327 !important +} + +.uk-text-danger { + color: #d85030 !important +} + +.uk-text-contrast { + color: #fff !important +} + +.uk-text-left { + text-align: left !important +} + +.uk-text-right { + text-align: right !important +} + +.uk-text-center { + text-align: center !important +} + +.uk-text-justify { + text-align: justify !important +} + +.uk-text-top { + vertical-align: top !important +} + +.uk-text-middle { + vertical-align: middle !important +} + +.uk-text-bottom { + vertical-align: bottom !important +} + +@media (max-width:959px) { + .uk-text-center-medium { + text-align: center !important + } + .uk-text-left-medium { + text-align: left !important + } +} + +@media (max-width:767px) { + .uk-text-center-small { + text-align: center !important + } + .uk-text-left-small { + text-align: left !important + } +} + +.uk-text-nowrap { + white-space: nowrap +} + +.uk-text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.uk-text-break { + word-wrap: break-word; + -webkit-hyphens: auto; + -ms-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto +} + +.uk-container { + box-sizing: border-box; + max-width: 980px; + padding: 0 25px +} + +@media (min-width:1220px) { + .uk-container { + max-width: 1200px; + padding: 0 35px + } +} + +.uk-container:before, +.uk-container:after { + content: ""; + display: table +} + +.uk-container:after { + clear: both +} + +.uk-container-center { + margin-left: auto; + margin-right: auto +} + +.uk-clearfix:before { + content: ""; + display: table-cell +} + +.uk-clearfix:after { + content: ""; + display: table; + clear: both +} + +.uk-nbfc { + overflow: hidden +} + +.uk-nbfc-alt { + display: table-cell; + width: 10000px +} + +.uk-float-left { + float: left +} + +.uk-float-right { + float: right +} + +[class*='uk-float-'] { + max-width: 100% +} + +[class*='uk-align-'] { + display: block; + margin-bottom: 15px +} + +.uk-align-left { + margin-right: 15px; + float: left +} + +.uk-align-right { + margin-left: 15px; + float: right +} + +@media (min-width:768px) { + .uk-align-medium-left { + margin-right: 15px; + float: left + } + .uk-align-medium-right { + margin-left: 15px; + float: right + } +} + +.uk-align-center { + margin-left: auto; + margin-right: auto +} + +.uk-vertical-align { + font-size: 0.001px +} + +.uk-vertical-align:before { + content: ''; + display: inline-block; + height: 100%; + vertical-align: middle +} + +.uk-vertical-align-middle, +.uk-vertical-align-bottom { + display: inline-block; + max-width: 100%; + font-size: 1rem +} + +.uk-vertical-align-middle { + vertical-align: middle +} + +.uk-vertical-align-bottom { + vertical-align: bottom +} + +[class*='uk-height'] { + box-sizing: border-box +} + +.uk-height-1-1 { + height: 100% +} + +.uk-height-viewport { + height: 100vh; + min-height: 600px +} + +.uk-responsive-width, +.uk-responsive-height { + box-sizing: border-box +} + +.uk-responsive-width { + max-width: 100% !important; + height: auto +} + +.uk-responsive-height { + max-height: 100%; + width: auto +} + +.uk-margin { + margin-bottom: 15px +} + +*+.uk-margin { + margin-top: 15px +} + +.uk-margin-top { + margin-top: 15px !important +} + +.uk-margin-bottom { + margin-bottom: 15px !important +} + +.uk-margin-left { + margin-left: 15px !important +} + +.uk-margin-right { + margin-right: 15px !important +} + +.uk-margin-large { + margin-bottom: 50px +} + +*+.uk-margin-large { + margin-top: 50px +} + +.uk-margin-large-top { + margin-top: 50px !important +} + +.uk-margin-large-bottom { + margin-bottom: 50px !important +} + +.uk-margin-large-left { + margin-left: 50px !important +} + +.uk-margin-large-right { + margin-right: 50px !important +} + +.uk-margin-small { + margin-bottom: 5px +} + +*+.uk-margin-small { + margin-top: 5px +} + +.uk-margin-small-top { + margin-top: 5px !important +} + +.uk-margin-small-bottom { + margin-bottom: 5px !important +} + +.uk-margin-small-left { + margin-left: 5px !important +} + +.uk-margin-small-right { + margin-right: 5px !important +} + +.uk-margin-remove { + margin: 0 !important +} + +.uk-margin-top-remove { + margin-top: 0 !important +} + +.uk-margin-bottom-remove { + margin-bottom: 0 !important +} + +.uk-padding-remove { + padding: 0 !important +} + +.uk-padding-top-remove { + padding-top: 0 !important +} + +.uk-padding-bottom-remove { + padding-bottom: 0 !important +} + +.uk-padding-vertical-remove { + padding-top: 0 !important; + padding-bottom: 0 !important +} + +.uk-border-circle { + border-radius: 50% +} + +.uk-border-rounded { + border-radius: 5px +} + +.uk-heading-large { + font-size: 36px; + line-height: 42px +} + +@media (min-width:768px) { + .uk-heading-large { + font-size: 52px; + line-height: 64px + } +} + +.uk-link-muted, +.uk-link-muted a { + color: #444 +} + +.uk-link-muted:hover, +.uk-link-muted a:hover { + color: #444 +} + +.uk-link-reset, +.uk-link-reset a, +.uk-link-reset:hover, +.uk-link-reset a:hover, +.uk-link-reset:focus, +.uk-link-reset a:focus { + color: inherit; + text-decoration: none +} + +.uk-scrollable-text { + height: 300px; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + resize: both +} + +.uk-scrollable-box { + box-sizing: border-box; + height: 170px; + padding: 10px; + border: 1px solid #ddd; + overflow: auto; + -webkit-overflow-scrolling: touch; + resize: both; + border-radius: 3px +} + +.uk-scrollable-box>:last-child { + margin-bottom: 0 +} + +.uk-overflow-hidden { + overflow: hidden +} + +.uk-overflow-container { + overflow: auto; + -webkit-overflow-scrolling: touch +} + +.uk-overflow-container>:last-child { + margin-bottom: 0 +} + +.uk-position-absolute, +[class*='uk-position-top'], +[class*='uk-position-bottom'] { + position: absolute !important +} + +.uk-position-top { + top: 0; + left: 0; + right: 0 +} + +.uk-position-bottom { + bottom: 0; + left: 0; + right: 0 +} + +.uk-position-top-left { + top: 0; + left: 0 +} + +.uk-position-top-right { + top: 0; + right: 0 +} + +.uk-position-bottom-left { + bottom: 0; + left: 0 +} + +.uk-position-bottom-right { + bottom: 0; + right: 0 +} + +.uk-position-cover { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0 +} + +.uk-position-relative { + position: relative !important +} + +.uk-position-z-index { + z-index: 1 +} + +.uk-display-block { + display: block !important +} + +.uk-display-inline { + display: inline !important +} + +.uk-display-inline-block { + display: inline-block !important; + max-width: 100% +} + +@media (min-width:960px) { + .uk-visible-small { + display: none !important + } + .uk-visible-medium { + display: none !important + } + .uk-hidden-large { + display: none !important + } +} + +@media (min-width:768px) and (max-width:959px) { + .uk-visible-small { + display: none !important + } + .uk-visible-large { + display: none !important + } + .uk-hidden-medium { + display: none !important + } +} + +@media (max-width:767px) { + .uk-visible-medium { + display: none !important + } + .uk-visible-large { + display: none !important + } + .uk-hidden-small { + display: none !important + } +} + +.uk-hidden { + display: none !important; + visibility: hidden !important +} + +.uk-invisible { + visibility: hidden !important +} + +.uk-visible-hover:hover .uk-hidden, +.uk-visible-hover:hover .uk-invisible { + display: block !important; + visibility: visible !important +} + +.uk-visible-hover-inline:hover .uk-hidden, +.uk-visible-hover-inline:hover .uk-invisible { + display: inline-block !important; + visibility: visible !important +} + +.uk-touch .uk-hidden-touch, +.uk-notouch .uk-hidden-notouch { + display: none !important +} + +.uk-flex { + display: -ms-flexbox; + display: -webkit-flex; + display: flex +} + +.uk-flex-inline { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex +} + +.uk-flex>*, +.uk-flex-inline>* { + -ms-flex-negative: 1 +} + +.uk-flex-top { + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start +} + +.uk-flex-middle { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center +} + +.uk-flex-bottom { + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end +} + +.uk-flex-center { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center +} + +.uk-flex-right { + -ms-flex-pack: end; + -webkit-justify-content: flex-end; + justify-content: flex-end +} + +.uk-flex-space-between { + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between +} + +.uk-flex-space-around { + -ms-flex-pack: distribute; + -webkit-justify-content: space-around; + justify-content: space-around +} + +.uk-flex-row-reverse { + -ms-flex-direction: row-reverse; + -webkit-flex-direction: row-reverse; + flex-direction: row-reverse +} + +.uk-flex-column { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column +} + +.uk-flex-column-reverse { + -ms-flex-direction: column-reverse; + -webkit-flex-direction: column-reverse; + flex-direction: column-reverse +} + +.uk-flex-nowrap { + -ms-flex-wrap: nowrap; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap +} + +.uk-flex-wrap { + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap +} + +.uk-flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse; + -webkit-flex-wrap: wrap-reverse; + flex-wrap: wrap-reverse +} + +.uk-flex-wrap-top { + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start +} + +.uk-flex-wrap-middle { + -ms-flex-line-pack: center; + -webkit-align-content: center; + align-content: center +} + +.uk-flex-wrap-bottom { + -ms-flex-line-pack: end; + -webkit-align-content: flex-end; + align-content: flex-end +} + +.uk-flex-wrap-space-between { + -ms-flex-line-pack: justify; + -webkit-align-content: space-between; + align-content: space-between +} + +.uk-flex-wrap-space-around { + -ms-flex-line-pack: distribute; + -webkit-align-content: space-around; + align-content: space-around +} + +.uk-flex-order-first { + -ms-flex-order: -1; + -webkit-order: -1; + order: -1 +} + +.uk-flex-order-last { + -ms-flex-order: 99; + -webkit-order: 99; + order: 99 +} + +@media (min-width:480px) { + .uk-flex-order-first-small { + -ms-flex-order: -1; + -webkit-order: -1; + order: -1 + } + .uk-flex-order-last-small { + -ms-flex-order: 99; + -webkit-order: 99; + order: 99 + } +} + +@media (min-width:768px) { + .uk-flex-order-first-medium { + -ms-flex-order: -1; + -webkit-order: -1; + order: -1 + } + .uk-flex-order-last-medium { + -ms-flex-order: 99; + -webkit-order: 99; + order: 99 + } +} + +@media (min-width:960px) { + .uk-flex-order-first-large { + -ms-flex-order: -1; + -webkit-order: -1; + order: -1 + } + .uk-flex-order-last-large { + -ms-flex-order: 99; + -webkit-order: 99; + order: 99 + } +} + +@media (min-width:1220px) { + .uk-flex-order-first-xlarge { + -ms-flex-order: -1; + -webkit-order: -1; + order: -1 + } + .uk-flex-order-last-xlarge { + -ms-flex-order: 99; + -webkit-order: 99; + order: 99 + } +} + +.uk-flex-item-none { + -ms-flex: none; + -webkit-flex: none; + flex: none +} + +.uk-flex-item-auto { + -ms-flex: auto; + -webkit-flex: auto; + flex: auto; + -ms-flex-negative: 1 +} + +.uk-flex-item-1 { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1 +} + +.uk-contrast { + color: #fff +} + +.uk-contrast a:not([class]), +.uk-contrast .uk-link { + color: rgba(255, 255, 255, 0.7); + text-decoration: none +} + +.uk-contrast a:not([class]):hover, +.uk-contrast .uk-link:hover { + color: #fff; + text-decoration: underline +} + +.uk-contrast:not(pre)>code, +.uk-contrast:not(pre)>kbd, +.uk-contrast:not(pre)>samp { + color: #fff; + border-color: rgba(255, 255, 255, 0.2); + background: rgba(255, 255, 255, 0.1) +} + +.uk-contrast em { + color: #fff +} + +.uk-contrast h1, +.uk-contrast h2, +.uk-contrast h3, +.uk-contrast h4, +.uk-contrast h5, +.uk-contrast h6 { + color: #fff +} + +.uk-contrast hr { + border-top-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-nav li>a, +.uk-contrast .uk-nav li>a:hover { + text-decoration: none +} + +.uk-contrast .uk-nav-side>li>a { + color: #fff +} + +.uk-contrast .uk-nav-side>li>a:hover, +.uk-contrast .uk-nav-side>li>a:focus { + background: rgba(255, 255, 255, 0.1); + color: #fff; + text-shadow: none +} + +.uk-contrast .uk-nav-side>li.uk-active>a { + background: #fff; + color: #444; + text-shadow: none +} + +.uk-contrast .uk-nav-side .uk-nav-header { + color: #fff +} + +.uk-contrast .uk-nav-side .uk-nav-divider { + border-top-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-nav-side ul a { + color: rgba(255, 255, 255, 0.7) +} + +.uk-contrast .uk-nav-side ul a:hover { + color: #fff +} + +.uk-contrast .uk-subnav>*>a { + color: rgba(255, 255, 255, 0.7); + text-decoration: none +} + +.uk-contrast .uk-subnav>*>a:hover, +.uk-contrast .uk-subnav>*>a:focus { + color: #fff; + text-decoration: none +} + +.uk-contrast .uk-subnav>.uk-active>a { + color: #fff +} + +.uk-contrast .uk-subnav-line>:nth-child(n+2):before { + border-left-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-subnav-pill>*>a:hover, +.uk-contrast .uk-subnav-pill>*>a:focus { + background: rgba(255, 255, 255, 0.7); + color: #444; + text-decoration: none +} + +.uk-contrast .uk-subnav-pill>.uk-active>a { + background: #fff; + color: #444 +} + +.uk-contrast .uk-tab { + border-bottom-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-tab>li>a { + border-color: transparent; + color: rgba(255, 255, 255, 0.7); + text-shadow: none +} + +.uk-contrast .uk-tab>li>a:hover, +.uk-contrast .uk-tab>li>a:focus, +.uk-contrast .uk-tab>li.uk-open>a { + border-color: rgba(255, 255, 255, 0.7); + background: rgba(255, 255, 255, 0.7); + color: #444; + text-decoration: none +} + +.uk-contrast .uk-tab>li.uk-active>a { + border-color: rgba(255, 255, 255, 0.2); + border-bottom-color: transparent; + background: #fff; + color: #444 +} + +.uk-contrast .uk-tab-center { + border-bottom-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-tab-grid:before { + border-top-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-list-line>li:nth-child(n+2) { + border-top-color: rgba(255, 255, 255, 0.2) +} + +.uk-contrast .uk-form select, +.uk-contrast .uk-form textarea, +.uk-contrast .uk-form input:not([type]), +.uk-contrast .uk-form input[type="text"], +.uk-contrast .uk-form input[type="password"], +.uk-contrast .uk-form input[type="datetime"], +.uk-contrast .uk-form input[type="datetime-local"], +.uk-contrast .uk-form input[type="date"], +.uk-contrast .uk-form input[type="month"], +.uk-contrast .uk-form input[type="time"], +.uk-contrast .uk-form input[type="week"], +.uk-contrast .uk-form input[type="number"], +.uk-contrast .uk-form input[type="email"], +.uk-contrast .uk-form input[type="url"], +.uk-contrast .uk-form input[type="search"], +.uk-contrast .uk-form input[type="tel"], +.uk-contrast .uk-form input[type="color"] { + border-color: rgba(255, 255, 255, 0.8); + background: rgba(255, 255, 255, 0.8); + color: #444; + background-clip: padding-box +} + +.uk-contrast .uk-form select:focus, +.uk-contrast .uk-form textarea:focus, +.uk-contrast .uk-form input:not([type]):focus, +.uk-contrast .uk-form input[type="text"]:focus, +.uk-contrast .uk-form input[type="password"]:focus, +.uk-contrast .uk-form input[type="datetime"]:focus, +.uk-contrast .uk-form input[type="datetime-local"]:focus, +.uk-contrast .uk-form input[type="date"]:focus, +.uk-contrast .uk-form input[type="month"]:focus, +.uk-contrast .uk-form input[type="time"]:focus, +.uk-contrast .uk-form input[type="week"]:focus, +.uk-contrast .uk-form input[type="number"]:focus, +.uk-contrast .uk-form input[type="email"]:focus, +.uk-contrast .uk-form input[type="url"]:focus, +.uk-contrast .uk-form input[type="search"]:focus, +.uk-contrast .uk-form input[type="tel"]:focus, +.uk-contrast .uk-form input[type="color"]:focus { + border-color: #fff; + background: #fff; + color: #444 +} + +.uk-contrast .uk-form:-ms-input-placeholder { + color: rgba(68, 68, 68, 0.7) !important +} + +.uk-contrast .uk-form::-moz-placeholder { + color: rgba(68, 68, 68, 0.7) +} + +.uk-contrast .uk-form::-webkit-input-placeholder { + color: rgba(68, 68, 68, 0.7) +} + +.uk-contrast .uk-button { + color: #444; + background: #fff; + border-color: transparent +} + +.uk-contrast .uk-button:hover, +.uk-contrast .uk-button:focus { + background-color: rgba(255, 255, 255, 0.8); + color: #444; + border-color: transparent +} + +.uk-contrast .uk-button:active, +.uk-contrast .uk-button.uk-active { + background-color: rgba(255, 255, 255, 0.7); + color: #444; + box-shadow: none +} + +.uk-contrast .uk-button-primary { + background-color: #009dd8; + color: #fff +} + +.uk-contrast .uk-button-primary:hover, +.uk-contrast .uk-button-primary:focus { + background-color: #00aff2; + color: #fff +} + +.uk-contrast .uk-button-primary:active, +.uk-contrast .uk-button-primary.uk-active { + background-color: #008abf; + color: #fff +} + +.uk-contrast .uk-icon-hover { + color: rgba(255, 255, 255, 0.7) +} + +.uk-contrast .uk-icon-hover:hover { + color: #fff +} + +.uk-contrast .uk-icon-button { + background: #fff; + color: #444; + border-color: transparent +} + +.uk-contrast .uk-icon-button:hover, +.uk-contrast .uk-icon-button:focus { + background-color: rgba(255, 255, 255, 0.8); + color: #444; + border-color: transparent +} + +.uk-contrast .uk-icon-button:active { + background-color: rgba(255, 255, 255, 0.7); + color: #444; + box-shadow: none +} + +.uk-contrast .uk-text-muted { + color: rgba(255, 255, 255, 0.6) !important +} + +.uk-contrast .uk-text-primary { + color: #2d7091 !important +} + +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: black !important; + box-shadow: none !important; + text-shadow: none !important + } + a, + a:visited { + text-decoration: underline + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid + } + thead { + display: table-header-group + } + tr, + img { + page-break-inside: avoid + } + img { + max-width: 100% !important + } + @page { + margin: 0.5cm + } + p, + h2, + h3 { + orphans: 3; + widows: 3 + } + h2, + h3 { + page-break-after: avoid + } +} + +.uk-dotnav { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: -15px; + margin-top: -15px; + padding: 0; + list-style: none +} + +.uk-dotnav>* { + -ms-flex: none; + -webkit-flex: none; + flex: none; + padding-left: 15px; + margin-top: 15px +} + +.uk-dotnav:before, +.uk-dotnav:after { + content: ""; + display: block; + overflow: hidden +} + +.uk-dotnav:after { + clear: both +} + +.uk-dotnav>* { + float: left +} + +.uk-dotnav>*>* { + display: block; + box-sizing: content-box; + width: 20px; + height: 20px; + border-radius: 50%; + background: rgba(50, 50, 50, 0.1); + text-indent: 100%; + overflow: hidden; + white-space: nowrap; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out +} + +.uk-dotnav>*>:hover, +.uk-dotnav>*>:focus { + background: rgba(50, 50, 50, 0.4); + outline: none +} + +.uk-dotnav>*>:active { + background: rgba(50, 50, 50, 0.6) +} + +.uk-dotnav>.uk-active>* { + background: rgba(50, 50, 50, 0.4); + -webkit-transform: scale(1.3); + transform: scale(1.3) +} + +.uk-dotnav-contrast>*>* { + background: rgba(255, 255, 255, 0.4) +} + +.uk-dotnav-contrast>*>:hover, +.uk-dotnav-contrast>*>:focus { + background: rgba(255, 255, 255, 0.7) +} + +.uk-dotnav-contrast>*>:active { + background: rgba(255, 255, 255, 0.9) +} + +.uk-dotnav-contrast>.uk-active>* { + background: rgba(255, 255, 255, 0.9) +} + +.uk-dotnav-vertical { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column +} + +.uk-dotnav-vertical>* { + float: none +} + +.uk-slidenav { + display: inline-block; + box-sizing: border-box; + width: 60px; + height: 60px; + line-height: 60px; + color: rgba(50, 50, 50, 0.4); + font-size: 60px; + text-align: center +} + +.uk-slidenav:hover, +.uk-slidenav:focus { + outline: none; + text-decoration: none; + color: rgba(50, 50, 50, 0.7); + cursor: pointer +} + +.uk-slidenav:active { + color: rgba(50, 50, 50, 0.9) +} + +.uk-slidenav-previous:before { + content: "\f104"; + font-family: FontAwesome +} + +.uk-slidenav-next:before { + content: "\f105"; + font-family: FontAwesome +} + +.uk-slidenav-position { + position: relative +} + +.uk-slidenav-position .uk-slidenav { + display: none; + position: absolute; + top: 50%; + z-index: 1; + margin-top: -30px +} + +.uk-slidenav-position:hover .uk-slidenav { + display: block +} + +.uk-slidenav-position .uk-slidenav-previous { + left: 20px +} + +.uk-slidenav-position .uk-slidenav-next { + right: 20px +} + +.uk-slidenav-contrast { + color: rgba(255, 255, 255, 0.5) +} + +.uk-slidenav-contrast:hover, +.uk-slidenav-contrast:focus { + color: rgba(255, 255, 255, 0.7) +} + +.uk-slidenav-contrast:active { + color: rgba(255, 255, 255, 0.9) +} + +.uk-form input[type="radio"], +.uk-form input[type="checkbox"] { + display: inline-block; + height: 14px; + width: 14px; + border: 1px solid #aaa; + overflow: hidden; + margin-top: -4px; + vertical-align: middle; + -webkit-appearance: none; + outline: 0; + background: transparent +} + +.uk-form input[type="radio"] { + border-radius: 50% +} + +.uk-form input[type=radio]:before, +.uk-form input[type=checkbox]:before { + display: block +} + +.uk-form input[type=radio]:checked:before { + content: ''; + width: 8px; + height: 8px; + margin: 2px auto 0; + border-radius: 50%; + background: #00a8e6 +} + +.uk-form input[type=checkbox]:checked:before, +.uk-form input[type=checkbox]:indeterminate:before { + content: "\f00c"; + font-family: FontAwesome; + font-size: 12px; + -webkit-font-smoothing: antialiased; + text-align: center; + line-height: 12px; + color: #00a8e6 +} + +.uk-form input[type=checkbox]:indeterminate:before { + content: "\f068" +} + +.uk-form input[type=radio]:disabled, +.uk-form input[type=checkbox]:disabled { + border-color: #ddd +} + +.uk-form input[type=radio]:disabled:checked:before { + background-color: #aaa +} + +.uk-form input[type=checkbox]:disabled:checked:before, +.uk-form input[type=checkbox]:disabled:indeterminate:before { + color: #aaa +} + +.uk-form-file { + display: inline-block; + vertical-align: middle; + position: relative; + overflow: hidden +} + +.uk-form-file input[type="file"] { + position: absolute; + top: 0; + z-index: 1; + width: 100%; + opacity: 0; + cursor: pointer; + left: 0; + font-size: 500px +} + +.uk-form-password { + display: inline-block; + position: relative; + max-width: 100% +} + +.uk-form-password-toggle { + display: block; + position: absolute; + top: 50%; + right: 10px; + margin-top: -6px; + font-size: 13px; + line-height: 13px; + color: #999 +} + +.uk-form-password-toggle:hover { + color: #999; + text-decoration: none +} + +.uk-form-password>input { + padding-right: 50px !important +} + +.uk-form-select { + display: inline-block; + vertical-align: middle; + position: relative; + overflow: hidden +} + +.uk-form-select select { + position: absolute; + top: 0; + z-index: 1; + width: 100%; + height: 100%; + opacity: 0; + cursor: pointer; + left: 0; + -webkit-appearance: none +} + +.uk-placeholder { + margin-bottom: 15px; + padding: 15px; + border: 1px dashed #ddd; + background: #fafafa; + color: #444 +} + +*+.uk-placeholder { + margin-top: 15px +} + +.uk-placeholder>:last-child { + margin-bottom: 0 +} + +.uk-placeholder-large { + padding-top: 80px; + padding-bottom: 80px +} + +.uk-progress { + box-sizing: border-box; + height: 20px; + margin-bottom: 15px; + background: #f7f7f7; + overflow: hidden; + line-height: 20px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.07), inset 0 2px 2px rgba(0, 0, 0, 0.07); + border-radius: 4px +} + +*+.uk-progress { + margin-top: 15px +} + +.uk-progress-bar { + width: 0; + height: 100%; + background: #009dd8; + float: left; + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; + font-size: 12px; + color: #fff; + text-align: center; + background-image: -webkit-linear-gradient(top, #00b4f5, #008dc5); + background-image: linear-gradient(to bottom, #00b4f5, #008dc5); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(0, 0, 0, 0.1); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-progress-mini { + height: 6px +} + +.uk-progress-small { + height: 12px +} + +.uk-progress-success .uk-progress-bar { + background-color: #82bb42; + background-image: -webkit-linear-gradient(top, #9fd256, #6fac34); + background-image: linear-gradient(to bottom, #9fd256, #6fac34) +} + +.uk-progress-warning .uk-progress-bar { + background-color: #f9a124; + background-image: -webkit-linear-gradient(top, #fbb450, #f89406); + background-image: linear-gradient(to bottom, #fbb450, #f89406) +} + +.uk-progress-danger .uk-progress-bar { + background-color: #d32c46; + background-image: -webkit-linear-gradient(top, #ee465a, #c11a39); + background-image: linear-gradient(to bottom, #ee465a, #c11a39) +} + +.uk-progress-striped .uk-progress-bar { + background-image: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 30px 30px +} + +.uk-progress-striped.uk-active .uk-progress-bar { + -webkit-animation: uk-progress-bar-stripes 2s linear infinite; + animation: uk-progress-bar-stripes 2s linear infinite +} + +@-webkit-keyframes uk-progress-bar-stripes { + 0% { + background-position: 0 0 + } + 100% { + background-position: 30px 0 + } +} + +@keyframes uk-progress-bar-stripes { + 0% { + background-position: 0 0 + } + 100% { + background-position: 30px 0 + } +} + +.uk-progress-mini, +.uk-progress-small { + border-radius: 500px +} + +.uk-accordion-title { + margin-top: 0; + margin-bottom: 15px; + padding: 5px 15px; + background: #f7f7f7; + font-size: 18px; + line-height: 24px; + cursor: pointer; + border: 1px solid #ddd; + border-radius: 4px +} + +.uk-accordion-content { + padding: 0 15px 15px 15px +} + +.uk-accordion-content:before, +.uk-accordion-content:after { + content: ""; + display: table +} + +.uk-accordion-content:after { + clear: both +} + +.uk-accordion-content>:last-child { + margin-bottom: 0 +} + +.uk-autocomplete { + display: inline-block; + position: relative; + max-width: 100%; + vertical-align: middle +} + +.uk-nav-autocomplete>li>a { + color: #444 +} + +.uk-nav-autocomplete>li.uk-active>a { + background: #009dd8; + color: #fff; + outline: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-nav-autocomplete .uk-nav-header { + color: #999 +} + +.uk-nav-autocomplete .uk-nav-divider { + border-top: 1px solid #ddd +} + +.uk-datepicker { + z-index: 1050; + width: auto; + -webkit-animation: uk-fade .2s ease-in-out; + animation: uk-fade .2s ease-in-out; + -webkit-transform-origin: 0 0; + transform-origin: 0 0 +} + +.uk-datepicker-nav { + margin-bottom: 15px; + text-align: center; + line-height: 20px +} + +.uk-datepicker-nav:before, +.uk-datepicker-nav:after { + content: ""; + display: table +} + +.uk-datepicker-nav:after { + clear: both +} + +.uk-datepicker-nav a { + color: #444; + text-decoration: none +} + +.uk-datepicker-nav a:hover { + color: #444 +} + +.uk-datepicker-previous { + float: left +} + +.uk-datepicker-next { + float: right +} + +.uk-datepicker-previous:after, +.uk-datepicker-next:after { + width: 20px; + font-family: FontAwesome +} + +.uk-datepicker-previous:after { + content: "\f053" +} + +.uk-datepicker-next:after { + content: "\f054" +} + +.uk-datepicker-table { + width: 100% +} + +.uk-datepicker-table th, +.uk-datepicker-table td { + padding: 2px +} + +.uk-datepicker-table th { + font-size: 12px +} + +.uk-datepicker-table a { + display: block; + width: 26px; + line-height: 24px; + text-align: center; + color: #444; + text-decoration: none; + border: 1px solid transparent; + border-radius: 4px; + background-origin: border-box +} + +a.uk-datepicker-table-muted { + color: #999 +} + +.uk-datepicker-table a:hover, +.uk-datepicker-table a:focus { + background-color: #fafafa; + color: #444; + outline: none; + border-color: rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.3); + text-shadow: 0 1px 0 #fff +} + +.uk-datepicker-table a:active { + background-color: #f5f5f5; + color: #444; + border-color: rgba(0, 0, 0, 0.2); + border-top-color: rgba(0, 0, 0, 0.3); + background-image: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-datepicker-table a.uk-active { + background: #009dd8; + color: #fff; + border: 1px solid rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.4); + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #00b4f5, #008dc5); + background-image: linear-gradient(to bottom, #00b4f5, #008dc5); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-htmleditor-navbar { + background: #f7f7f7; + border: 1px solid rgba(0, 0, 0, 0.1); + border-bottom-color: rgba(0, 0, 0, 0.2); + border-top-left-radius: 4px; + border-top-right-radius: 4px; + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #fff, #eee); + background-image: linear-gradient(to bottom, #fff, #eee) +} + +.uk-htmleditor-navbar:before, +.uk-htmleditor-navbar:after { + content: ""; + display: table +} + +.uk-htmleditor-navbar:after { + clear: both +} + +.uk-htmleditor-navbar-nav { + margin: 0; + padding: 0; + list-style: none; + float: left +} + +.uk-htmleditor-navbar-nav>li { + float: left +} + +.uk-htmleditor-navbar-nav>li>a { + display: block; + box-sizing: border-box; + text-decoration: none; + height: 41px; + padding: 0 15px; + line-height: 40px; + color: #444; + font-size: 11px; + cursor: pointer; + margin-top: -1px; + margin-left: -1px; + border: 1px solid transparent; + border-bottom-width: 0; + text-shadow: 0 1px 0 #fff +} + +.uk-htmleditor-navbar-nav>li:hover>a, +.uk-htmleditor-navbar-nav>li>a:focus { + background-color: transparent; + color: #444; + outline: none; + position: relative; + z-index: 1; + border-left-color: rgba(0, 0, 0, 0.1); + border-right-color: rgba(0, 0, 0, 0.1); + border-top-color: rgba(0, 0, 0, 0.1); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-htmleditor-navbar-nav>li>a:active { + background-color: #f5f5f5; + color: #444; + border-left-color: rgba(0, 0, 0, 0.1); + border-right-color: rgba(0, 0, 0, 0.1); + border-top-color: rgba(0, 0, 0, 0.2); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-htmleditor-navbar-nav>li.uk-active>a { + background-color: #fafafa; + color: #444; + border-left-color: rgba(0, 0, 0, 0.1); + border-right-color: rgba(0, 0, 0, 0.1); + border-top-color: rgba(0, 0, 0, 0.2); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1) +} + +.uk-htmleditor-navbar-flip { + float: right +} + +[data-mode='split'] .uk-htmleditor-button-code, +[data-mode='split'] .uk-htmleditor-button-preview { + display: none +} + +.uk-htmleditor-content { + border-left: 1px solid #ddd; + border-right: 1px solid #ddd; + border-bottom: 1px solid #ddd; + background: #fff; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px +} + +.uk-htmleditor-content:before, +.uk-htmleditor-content:after { + content: ""; + display: table +} + +.uk-htmleditor-content:after { + clear: both +} + +.uk-htmleditor-fullscreen { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 990 +} + +.uk-htmleditor-fullscreen .uk-htmleditor-content { + position: absolute; + top: 41px; + left: 0; + right: 0; + bottom: 0 +} + +.uk-htmleditor-fullscreen .uk-icon-expand:before { + content: "\f066" +} + +.uk-htmleditor-code, +.uk-htmleditor-preview { + box-sizing: border-box +} + +.uk-htmleditor-preview { + padding: 20px; + overflow-y: scroll; + position: relative +} + +[data-mode='tab'][data-active-tab='code'] .uk-htmleditor-preview, +[data-mode='tab'][data-active-tab='preview'] .uk-htmleditor-code { + display: none +} + +[data-mode='split'] .uk-htmleditor-code, +[data-mode='split'] .uk-htmleditor-preview { + float: left; + width: 50% +} + +[data-mode='split'] .uk-htmleditor-code { + border-right: 1px solid #eee +} + +.uk-htmleditor-iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100% +} + +.uk-htmleditor .CodeMirror { + padding: 10px; + box-sizing: border-box +} + +.uk-htmleditor-navbar-nav:first-child>li:first-child>a { + border-top-left-radius: 4px +} + +.uk-htmleditor-navbar-flip .uk-htmleditor-navbar-nav>li>a { + margin-left: 0; + margin-right: -1px +} + +.uk-htmleditor-navbar-flip .uk-htmleditor-navbar-nav:first-child>li:first-child>a { + border-top-left-radius: 0 +} + +.uk-htmleditor-navbar-flip .uk-htmleditor-navbar-nav:last-child>li:last-child>a { + border-top-right-radius: 4px +} + +.uk-htmleditor-fullscreen .uk-htmleditor-navbar { + border-top: none; + border-left: none; + border-right: none; + border-radius: 0 +} + +.uk-htmleditor-fullscreen .uk-htmleditor-content { + border: none; + border-radius: 0 +} + +.uk-htmleditor-fullscreen .uk-htmleditor-navbar-nav>li>a { + border-radius: 0 !important +} + +.uk-slider { + position: relative; + z-index: 0; + touch-action: pan-y +} + +.uk-slider:not(.uk-grid) { + margin: 0; + padding: 0; + list-style: none +} + +.uk-slider>* { + position: absolute; + top: 0; + left: 0 +} + +.uk-slider-container { + overflow: hidden +} + +.uk-slider:not(.uk-drag) { + -webkit-transition: -webkit-transform 200ms linear; + transition: transform 200ms linear +} + +.uk-slider.uk-drag { + cursor: col-resize; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none +} + +.uk-slider a, +.uk-slider img { + -webkit-user-drag: none; + user-drag: none; + -webkit-touch-callout: none +} + +.uk-slider img { + pointer-events: none +} + +.uk-slider-fullscreen, +.uk-slider-fullscreen>li { + height: 100vh +} + +.uk-slideshow { + position: relative; + z-index: 0; + width: 100%; + margin: 0; + padding: 0; + list-style: none; + overflow: hidden; + touch-action: pan-y +} + +.uk-slideshow>li { + position: absolute; + top: 0; + left: 0; + width: 100%; + opacity: 0 +} + +.uk-slideshow>.uk-active { + z-index: 10; + opacity: 1 +} + +.uk-slideshow>li>img { + visibility: hidden +} + +[data-uk-slideshow-slide] { + cursor: pointer +} + +.uk-slideshow-fullscreen, +.uk-slideshow-fullscreen>li { + height: 100vh +} + +.uk-slideshow-fade-in { + -webkit-animation: uk-fade .5s linear; + animation: uk-fade .5s linear +} + +.uk-slideshow-fade-out { + -webkit-animation: uk-fade .5s linear reverse; + animation: uk-fade .5s linear reverse +} + +.uk-slideshow-scroll-forward-in { + -webkit-animation: uk-slide-right .5s ease-in-out; + animation: uk-slide-right .5s ease-in-out +} + +.uk-slideshow-scroll-forward-out { + -webkit-animation: uk-slide-left .5s ease-in-out reverse; + animation: uk-slide-left .5s ease-in-out reverse +} + +.uk-slideshow-scroll-backward-in { + -webkit-animation: uk-slide-left .5s ease-in-out; + animation: uk-slide-left .5s ease-in-out +} + +.uk-slideshow-scroll-backward-out { + -webkit-animation: uk-slide-right .5s ease-in-out reverse; + animation: uk-slide-right .5s ease-in-out reverse +} + +.uk-slideshow-scale-out { + -webkit-animation: uk-fade-scale-15 .5s ease-in-out reverse; + animation: uk-fade-scale-15 .5s ease-in-out reverse +} + +.uk-slideshow-swipe-forward-in { + -webkit-animation: uk-slide-left-33 .5s ease-in-out; + animation: uk-slide-left-33 .5s ease-in-out +} + +.uk-slideshow-swipe-forward-out { + -webkit-animation: uk-slide-left .5s ease-in-out reverse; + animation: uk-slide-left .5s ease-in-out reverse +} + +.uk-slideshow-swipe-backward-in { + -webkit-animation: uk-slide-right-33 .5s ease-in-out; + animation: uk-slide-right-33 .5s ease-in-out +} + +.uk-slideshow-swipe-backward-out { + -webkit-animation: uk-slide-right .5s ease-in-out reverse; + animation: uk-slide-right .5s ease-in-out reverse +} + +.uk-slideshow-swipe-forward-in:before, +.uk-slideshow-swipe-backward-in:before { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1; + background: rgba(0, 0, 0, 0.6); + -webkit-animation: uk-fade .5s ease-in-out reverse; + animation: uk-fade .5s ease-in-out reverse +} + +.uk-notify { + position: fixed; + top: 10px; + left: 10px; + z-index: 1040; + box-sizing: border-box; + width: 350px +} + +.uk-notify-top-right, +.uk-notify-bottom-right { + left: auto; + right: 10px +} + +.uk-notify-top-center, +.uk-notify-bottom-center { + left: 50%; + margin-left: -175px +} + +.uk-notify-bottom-left, +.uk-notify-bottom-right, +.uk-notify-bottom-center { + top: auto; + bottom: 10px +} + +@media (max-width:479px) { + .uk-notify { + left: 10px; + right: 10px; + width: auto; + margin: 0 + } +} + +.uk-notify-message { + position: relative; + margin-bottom: 10px; + padding: 15px; + background: #444; + color: #fff; + font-size: 16px; + line-height: 22px; + cursor: pointer; + border: 1px solid #444; + border-radius: 4px +} + +.uk-notify-message>.uk-close { + visibility: hidden; + float: right +} + +.uk-notify-message:hover>.uk-close { + visibility: visible +} + +.uk-notify-message-primary { + background: #ebf7fd; + color: #2d7091; + border-color: rgba(45, 112, 145, 0.3) +} + +.uk-notify-message-success { + background: #f2fae3; + color: #659f13; + border-color: rgba(101, 159, 19, 0.3) +} + +.uk-notify-message-warning { + background: #fffceb; + color: #e28327; + border-color: rgba(226, 131, 39, 0.3) +} + +.uk-notify-message-danger { + background: #fff1f0; + color: #d85030; + border-color: rgba(216, 80, 48, 0.3) +} + +.uk-search { + display: inline-block; + position: relative; + margin: 0 +} + +.uk-search:before { + content: "\f002"; + position: absolute; + top: 0; + left: 0; + width: 30px; + line-height: 30px; + text-align: center; + font-family: FontAwesome; + font-size: 14px; + color: rgba(0, 0, 0, 0.2) +} + +.uk-search-field::-moz-focus-inner { + border: 0; + padding: 0 +} + +.uk-search-field::-webkit-search-cancel-button, +.uk-search-field::-webkit-search-decoration { + -webkit-appearance: none +} + +.uk-search-field::-ms-clear { + display: none +} + +.uk-search-field::-moz-placeholder { + opacity: 1 +} + +.uk-search-field { + box-sizing: border-box; + margin: 0; + border-radius: 0; + font: inherit; + color: #444; + -webkit-appearance: none; + width: 120px; + height: 30px; + padding: 0 0 0 30px; + border: 1px solid rgba(0, 0, 0, 0); + background: rgba(0, 0, 0, 0); + -webkit-transition: all linear 0.2s; + transition: all linear 0.2s; + vertical-align: middle +} + +.uk-search-field:-ms-input-placeholder { + color: #999 !important +} + +.uk-search-field::-moz-placeholder { + color: #999 +} + +.uk-search-field::-webkit-input-placeholder { + color: #999 +} + +.uk-search-field:focus { + outline: 0 +} + +.uk-search-field:focus, +.uk-search.uk-active .uk-search-field { + width: 180px +} + +.uk-dropdown-search { + width: 300px; + margin-top: 0; + background: #fff; + color: #444 +} + +.uk-open>.uk-dropdown-search { + -webkit-animation: uk-slide-top-fixed .2s ease-in-out; + animation: uk-slide-top-fixed .2s ease-in-out +} + +.uk-navbar-flip .uk-dropdown-search { + margin-top: 12px; + margin-right: -16px +} + +.uk-nav-search>li>a { + color: #444 +} + +.uk-nav-search>li.uk-active>a { + background: #009dd8; + color: #fff; + outline: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2) +} + +.uk-nav-search .uk-nav-header { + color: #999 +} + +.uk-nav-search .uk-nav-divider { + border-top: 1px solid #ddd +} + +.uk-nav-search ul a { + color: #07d +} + +.uk-nav-search ul a:hover { + color: #059 +} + +.uk-offcanvas .uk-search { + display: block; + margin: 20px 15px +} + +.uk-offcanvas .uk-search:before { + color: #777 +} + +.uk-offcanvas .uk-search-field { + width: 100%; + border-color: rgba(0, 0, 0, 0); + background: #1a1a1a; + color: #ccc +} + +.uk-offcanvas .uk-search-field:-ms-input-placeholder { + color: #777 !important +} + +.uk-offcanvas .uk-search-field::-moz-placeholder { + color: #777 +} + +.uk-offcanvas .uk-search-field::-webkit-input-placeholder { + color: #777 +} + +.uk-nestable { + padding: 0; + list-style: none +} + +.uk-nestable a, +.uk-nestable img { + -webkit-touch-callout: none +} + +.uk-nestable-list { + margin: 0; + padding-left: 40px; + list-style: none +} + +.uk-nestable-item { + touch-action: none +} + +.uk-nestable-item+.uk-nestable-item { + margin-top: 10px +} + +.uk-nestable-list:not(.uk-nestable-dragged)>.uk-nestable-item:first-child { + margin-top: 10px +} + +.uk-nestable-dragged { + position: absolute; + z-index: 1050; + pointer-events: none; + padding-left: 0 +} + +.uk-nestable-placeholder { + position: relative +} + +.uk-nestable-placeholder>* { + opacity: 0 +} + +.uk-nestable-placeholder:after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + border: 1px dashed #ddd; + opacity: 1 +} + +.uk-nestable-empty { + min-height: 30px +} + +.uk-nestable-handle { + touch-action: none +} + +.uk-nestable-handle:hover { + cursor: move +} + +.uk-nestable-moving, +.uk-nestable-moving * { + cursor: move +} + +[data-nestable-action='toggle'] { + cursor: pointer; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none +} + +.uk-nestable-toggle { + display: inline-block; + visibility: hidden +} + +.uk-nestable-toggle:after { + content: "\f147"; + font-family: FontAwesome +} + +.uk-parent>:not(.uk-nestable-list) .uk-nestable-toggle { + visibility: visible +} + +.uk-collapsed .uk-nestable-list { + display: none +} + +.uk-collapsed .uk-nestable-toggle:after { + content: "\f196" +} + +.uk-nestable-panel { + padding: 5px; + background: #f7f7f7; + border-radius: 4px; + border: 1px solid rgba(0, 0, 0, 0.2); + border-bottom-color: rgba(0, 0, 0, 0.3); + background-origin: border-box; + background-image: -webkit-linear-gradient(top, #fff, #eee); + background-image: linear-gradient(to bottom, #fff, #eee); + text-shadow: 0 1px 0 #fff +} + +.uk-sortable { + position: relative +} + +.uk-sortable>* { + touch-action: none +} + +.uk-sortable a, +.uk-sortable img { + -webkit-touch-callout: none +} + +.uk-sortable>:last-child { + margin-bottom: 0 +} + +.uk-sortable-dragged { + position: absolute; + z-index: 1050; + pointer-events: none +} + +.uk-sortable-placeholder { + opacity: 0 +} + +.uk-sortable-empty { + min-height: 30px +} + +.uk-sortable-handle { + touch-action: none +} + +.uk-sortable-handle:hover { + cursor: move +} + +.uk-sortable-moving, +.uk-sortable-moving * { + cursor: move +} + +[data-uk-sticky].uk-active { + z-index: 980; + box-sizing: border-box +} + +.uk-sticky-placeholder>* { + -webkit-backface-visibility: hidden; + backface-visibility: hidden +} + +[data-uk-sticky][class*='uk-animation-'] { + -webkit-animation-duration: .2s; + animation-duration: .2s +} + +[data-uk-sticky].uk-animation-reverse { + -webkit-animation-duration: .2s; + animation-duration: .2s +} + +.uk-dragover { + box-shadow: 0 0 20px rgba(100, 100, 100, 0.3) +} + +.uk-tooltip { + display: none; + position: absolute; + z-index: 1030; + box-sizing: border-box; + max-width: 200px; + padding: 5px 8px; + background: #333; + color: rgba(255, 255, 255, 0.7); + font-size: 12px; + line-height: 18px; + border-radius: 3px; + text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5) +} + +.uk-tooltip:after { + content: ""; + display: block; + position: absolute; + width: 0; + height: 0; + border: 5px dashed #333 +} + +.uk-tooltip-top:after, +.uk-tooltip-top-left:after, +.uk-tooltip-top-right:after { + bottom: -5px; + border-top-style: solid; + border-bottom: none; + border-left-color: transparent; + border-right-color: transparent; + border-top-color: #333 +} + +.uk-tooltip-bottom:after, +.uk-tooltip-bottom-left:after, +.uk-tooltip-bottom-right:after { + top: -5px; + border-bottom-style: solid; + border-top: none; + border-left-color: transparent; + border-right-color: transparent; + border-bottom-color: #333 +} + +.uk-tooltip-top:after, +.uk-tooltip-bottom:after { + left: 50%; + margin-left: -5px +} + +.uk-tooltip-top-left:after, +.uk-tooltip-bottom-left:after { + left: 10px +} + +.uk-tooltip-top-right:after, +.uk-tooltip-bottom-right:after { + right: 10px +} + +.uk-tooltip-left:after { + right: -5px; + top: 50%; + margin-top: -5px; + border-left-style: solid; + border-right: none; + border-top-color: transparent; + border-bottom-color: transparent; + border-left-color: #333 +} + +.uk-tooltip-right:after { + left: -5px; + top: 50%; + margin-top: -5px; + border-right-style: solid; + border-left: none; + border-top-color: transparent; + border-bottom-color: transparent; + border-right-color: #333 +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docs/tutorial/uikit.js Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,3750 @@ +/*! UIkit 2.25.0 | http://www.getuikit.com | (c) 2014 YOOtheme | MIT License */ +(function(core) { + + if (typeof define == "function" && define.amd) { // AMD + + define("uikit", function(){ + + var uikit = window.UIkit || core(window, window.jQuery, window.document); + + uikit.load = function(res, req, onload, config) { + + var resources = res.split(','), load = [], i, base = (config.config && config.config.uikit && config.config.uikit.base ? config.config.uikit.base : "").replace(/\/+$/g, ""); + + if (!base) { + throw new Error( "Please define base path to UIkit in the requirejs config." ); + } + + for (i = 0; i < resources.length; i += 1) { + var resource = resources[i].replace(/\./g, '/'); + load.push(base+'/components/'+resource); + } + + req(load, function() { + onload(uikit); + }); + }; + + return uikit; + }); + } + + if (!window.jQuery) { + throw new Error( "UIkit requires jQuery" ); + } + + if (window && window.jQuery) { + core(window, window.jQuery, window.document); + } + + +})(function(global, $, doc) { + + "use strict"; + + var UI = {}, _UI = global.UIkit ? Object.create(global.UIkit) : undefined; + + UI.version = '2.25.0'; + + UI.noConflict = function() { + // restore UIkit version + if (_UI) { + global.UIkit = _UI; + $.UIkit = _UI; + $.fn.uk = _UI.fn; + } + + return UI; + }; + + UI.prefix = function(str) { + return str; + }; + + // cache jQuery + UI.$ = $; + + UI.$doc = UI.$(document); + UI.$win = UI.$(window); + UI.$html = UI.$('html'); + + UI.support = {}; + UI.support.transition = (function() { + + var transitionEnd = (function() { + + var element = doc.body || doc.documentElement, + transEndEventNames = { + WebkitTransition : 'webkitTransitionEnd', + MozTransition : 'transitionend', + OTransition : 'oTransitionEnd otransitionend', + transition : 'transitionend' + }, name; + + for (name in transEndEventNames) { + if (element.style[name] !== undefined) return transEndEventNames[name]; + } + }()); + + return transitionEnd && { end: transitionEnd }; + })(); + + UI.support.animation = (function() { + + var animationEnd = (function() { + + var element = doc.body || doc.documentElement, + animEndEventNames = { + WebkitAnimation : 'webkitAnimationEnd', + MozAnimation : 'animationend', + OAnimation : 'oAnimationEnd oanimationend', + animation : 'animationend' + }, name; + + for (name in animEndEventNames) { + if (element.style[name] !== undefined) return animEndEventNames[name]; + } + }()); + + return animationEnd && { end: animationEnd }; + })(); + + // requestAnimationFrame polyfill + //https://github.com/darius/requestAnimationFrame + (function() { + + Date.now = Date.now || function() { return new Date().getTime(); }; + + var vendors = ['webkit', 'moz']; + for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { + var vp = vendors[i]; + window.requestAnimationFrame = window[vp+'RequestAnimationFrame']; + window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame'] + || window[vp+'CancelRequestAnimationFrame']); + } + if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy + || !window.requestAnimationFrame || !window.cancelAnimationFrame) { + var lastTime = 0; + window.requestAnimationFrame = function(callback) { + var now = Date.now(); + var nextTime = Math.max(lastTime + 16, now); + return setTimeout(function() { callback(lastTime = nextTime); }, + nextTime - now); + }; + window.cancelAnimationFrame = clearTimeout; + } + }()); + + UI.support.touch = ( + ('ontouchstart' in document) || + (global.DocumentTouch && document instanceof global.DocumentTouch) || + (global.navigator.msPointerEnabled && global.navigator.msMaxTouchPoints > 0) || //IE 10 + (global.navigator.pointerEnabled && global.navigator.maxTouchPoints > 0) || //IE >=11 + false + ); + + UI.support.mutationobserver = (global.MutationObserver || global.WebKitMutationObserver || null); + + UI.Utils = {}; + + UI.Utils.isFullscreen = function() { + return document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement || document.fullscreenElement || false; + }; + + UI.Utils.str2json = function(str, notevil) { + try { + if (notevil) { + return JSON.parse(str + // wrap keys without quote with valid double quote + .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":';}) + // replacing single quote wrapped ones to double quote + .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"';}) + ); + } else { + return (new Function("", "var json = " + str + "; return JSON.parse(JSON.stringify(json));"))(); + } + } catch(e) { return false; } + }; + + UI.Utils.debounce = function(func, wait, immediate) { + var timeout; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) func.apply(context, args); + }; + }; + + UI.Utils.removeCssRules = function(selectorRegEx) { + var idx, idxs, stylesheet, _i, _j, _k, _len, _len1, _len2, _ref; + + if(!selectorRegEx) return; + + setTimeout(function(){ + try { + _ref = document.styleSheets; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + stylesheet = _ref[_i]; + idxs = []; + stylesheet.cssRules = stylesheet.cssRules; + for (idx = _j = 0, _len1 = stylesheet.cssRules.length; _j < _len1; idx = ++_j) { + if (stylesheet.cssRules[idx].type === CSSRule.STYLE_RULE && selectorRegEx.test(stylesheet.cssRules[idx].selectorText)) { + idxs.unshift(idx); + } + } + for (_k = 0, _len2 = idxs.length; _k < _len2; _k++) { + stylesheet.deleteRule(idxs[_k]); + } + } + } catch (_error) {} + }, 0); + }; + + UI.Utils.isInView = function(element, options) { + + var $element = $(element); + + if (!$element.is(':visible')) { + return false; + } + + var window_left = UI.$win.scrollLeft(), window_top = UI.$win.scrollTop(), offset = $element.offset(), left = offset.left, top = offset.top; + + options = $.extend({topoffset:0, leftoffset:0}, options); + + if (top + $element.height() >= window_top && top - options.topoffset <= window_top + UI.$win.height() && + left + $element.width() >= window_left && left - options.leftoffset <= window_left + UI.$win.width()) { + return true; + } else { + return false; + } + }; + + UI.Utils.checkDisplay = function(context, initanimation) { + + var elements = UI.$('[data-uk-margin], [data-uk-grid-match], [data-uk-grid-margin], [data-uk-check-display]', context || document), animated; + + if (context && !elements.length) { + elements = $(context); + } + + elements.trigger('display.uk.check'); + + // fix firefox / IE animations + if (initanimation) { + + if (typeof(initanimation)!='string') { + initanimation = '[class*="uk-animation-"]'; + } + + elements.find(initanimation).each(function(){ + + var ele = UI.$(this), + cls = ele.attr('class'), + anim = cls.match(/uk\-animation\-(.+)/); + + ele.removeClass(anim[0]).width(); + + ele.addClass(anim[0]); + }); + } + + return elements; + }; + + UI.Utils.options = function(string) { + + if ($.type(string)!='string') return string; + + if (string.indexOf(':') != -1 && string.trim().substr(-1) != '}') { + string = '{'+string+'}'; + } + + var start = (string ? string.indexOf("{") : -1), options = {}; + + if (start != -1) { + try { + options = UI.Utils.str2json(string.substr(start)); + } catch (e) {} + } + + return options; + }; + + UI.Utils.animate = function(element, cls) { + + var d = $.Deferred(); + + element = UI.$(element); + + element.css('display', 'none').addClass(cls).one(UI.support.animation.end, function() { + element.removeClass(cls); + d.resolve(); + }); + + element.css('display', ''); + + return d.promise(); + }; + + UI.Utils.uid = function(prefix) { + return (prefix || 'id') + (new Date().getTime())+"RAND"+(Math.ceil(Math.random() * 100000)); + }; + + UI.Utils.template = function(str, data) { + + var tokens = str.replace(/\n/g, '\\n').replace(/\{\{\{\s*(.+?)\s*\}\}\}/g, "{{!$1}}").split(/(\{\{\s*(.+?)\s*\}\})/g), + i=0, toc, cmd, prop, val, fn, output = [], openblocks = 0; + + while(i < tokens.length) { + + toc = tokens[i]; + + if(toc.match(/\{\{\s*(.+?)\s*\}\}/)) { + i = i + 1; + toc = tokens[i]; + cmd = toc[0]; + prop = toc.substring(toc.match(/^(\^|\#|\!|\~|\:)/) ? 1:0); + + switch(cmd) { + case '~': + output.push("for(var $i=0;$i<"+prop+".length;$i++) { var $item = "+prop+"[$i];"); + openblocks++; + break; + case ':': + output.push("for(var $key in "+prop+") { var $val = "+prop+"[$key];"); + openblocks++; + break; + case '#': + output.push("if("+prop+") {"); + openblocks++; + break; + case '^': + output.push("if(!"+prop+") {"); + openblocks++; + break; + case '/': + output.push("}"); + openblocks--; + break; + case '!': + output.push("__ret.push("+prop+");"); + break; + default: + output.push("__ret.push(escape("+prop+"));"); + break; + } + } else { + output.push("__ret.push('"+toc.replace(/\'/g, "\\'")+"');"); + } + i = i + 1; + } + + fn = new Function('$data', [ + 'var __ret = [];', + 'try {', + 'with($data){', (!openblocks ? output.join('') : '__ret = ["Not all blocks are closed correctly."]'), '};', + '}catch(e){__ret = [e.message];}', + 'return __ret.join("").replace(/\\n\\n/g, "\\n");', + "function escape(html) { return String(html).replace(/&/g, '&').replace(/\"/g, '"').replace(/</g, '<').replace(/>/g, '>');}" + ].join("\n")); + + return data ? fn(data) : fn; + }; + + UI.Utils.events = {}; + UI.Utils.events.click = UI.support.touch ? 'tap' : 'click'; + + global.UIkit = UI; + + // deprecated + + UI.fn = function(command, options) { + + var args = arguments, cmd = command.match(/^([a-z\-]+)(?:\.([a-z]+))?/i), component = cmd[1], method = cmd[2]; + + if (!UI[component]) { + $.error("UIkit component [" + component + "] does not exist."); + return this; + } + + return this.each(function() { + var $this = $(this), data = $this.data(component); + if (!data) $this.data(component, (data = UI[component](this, method ? undefined : options))); + if (method) data[method].apply(data, Array.prototype.slice.call(args, 1)); + }); + }; + + $.UIkit = UI; + $.fn.uk = UI.fn; + + UI.langdirection = UI.$html.attr("dir") == "rtl" ? "right" : "left"; + + UI.components = {}; + + UI.component = function(name, def) { + + var fn = function(element, options) { + + var $this = this; + + this.UIkit = UI; + this.element = element ? UI.$(element) : null; + this.options = $.extend(true, {}, this.defaults, options); + this.plugins = {}; + + if (this.element) { + this.element.data(name, this); + } + + this.init(); + + (this.options.plugins.length ? this.options.plugins : Object.keys(fn.plugins)).forEach(function(plugin) { + + if (fn.plugins[plugin].init) { + fn.plugins[plugin].init($this); + $this.plugins[plugin] = true; + } + + }); + + this.trigger('init.uk.component', [name, this]); + + return this; + }; + + fn.plugins = {}; + + $.extend(true, fn.prototype, { + + defaults : {plugins: []}, + + boot: function(){}, + init: function(){}, + + on: function(a1,a2,a3){ + return UI.$(this.element || this).on(a1,a2,a3); + }, + + one: function(a1,a2,a3){ + return UI.$(this.element || this).one(a1,a2,a3); + }, + + off: function(evt){ + return UI.$(this.element || this).off(evt); + }, + + trigger: function(evt, params) { + return UI.$(this.element || this).trigger(evt, params); + }, + + find: function(selector) { + return UI.$(this.element ? this.element: []).find(selector); + }, + + proxy: function(obj, methods) { + + var $this = this; + + methods.split(' ').forEach(function(method) { + if (!$this[method]) $this[method] = function() { return obj[method].apply(obj, arguments); }; + }); + }, + + mixin: function(obj, methods) { + + var $this = this; + + methods.split(' ').forEach(function(method) { + if (!$this[method]) $this[method] = obj[method].bind($this); + }); + }, + + option: function() { + + if (arguments.length == 1) { + return this.options[arguments[0]] || undefined; + } else if (arguments.length == 2) { + this.options[arguments[0]] = arguments[1]; + } + } + + }, def); + + this.components[name] = fn; + + this[name] = function() { + + var element, options; + + if (arguments.length) { + + switch(arguments.length) { + case 1: + + if (typeof arguments[0] === "string" || arguments[0].nodeType || arguments[0] instanceof jQuery) { + element = $(arguments[0]); + } else { + options = arguments[0]; + } + + break; + case 2: + + element = $(arguments[0]); + options = arguments[1]; + break; + } + } + + if (element && element.data(name)) { + return element.data(name); + } + + return (new UI.components[name](element, options)); + }; + + if (UI.domready) { + UI.component.boot(name); + } + + return fn; + }; + + UI.plugin = function(component, name, def) { + this.components[component].plugins[name] = def; + }; + + UI.component.boot = function(name) { + + if (UI.components[name].prototype && UI.components[name].prototype.boot && !UI.components[name].booted) { + UI.components[name].prototype.boot.apply(UI, []); + UI.components[name].booted = true; + } + }; + + UI.component.bootComponents = function() { + + for (var component in UI.components) { + UI.component.boot(component); + } + }; + + + // DOM mutation save ready helper function + + UI.domObservers = []; + UI.domready = false; + + UI.ready = function(fn) { + + UI.domObservers.push(fn); + + if (UI.domready) { + fn(document); + } + }; + + UI.on = function(a1,a2,a3){ + + if (a1 && a1.indexOf('ready.uk.dom') > -1 && UI.domready) { + a2.apply(UI.$doc); + } + + return UI.$doc.on(a1,a2,a3); + }; + + UI.one = function(a1,a2,a3){ + + if (a1 && a1.indexOf('ready.uk.dom') > -1 && UI.domready) { + a2.apply(UI.$doc); + return UI.$doc; + } + + return UI.$doc.one(a1,a2,a3); + }; + + UI.trigger = function(evt, params) { + return UI.$doc.trigger(evt, params); + }; + + UI.domObserve = function(selector, fn) { + + if(!UI.support.mutationobserver) return; + + fn = fn || function() {}; + + UI.$(selector).each(function() { + + var element = this, + $element = UI.$(element); + + if ($element.data('observer')) { + return; + } + + try { + + var observer = new UI.support.mutationobserver(UI.Utils.debounce(function(mutations) { + fn.apply(element, []); + $element.trigger('changed.uk.dom'); + }, 50)); + + // pass in the target node, as well as the observer options + observer.observe(element, { childList: true, subtree: true }); + + $element.data('observer', observer); + + } catch(e) {} + }); + }; + + UI.init = function(root) { + + root = root || document; + + UI.domObservers.forEach(function(fn){ + fn(root); + }); + }; + + UI.on('domready.uk.dom', function(){ + + UI.init(); + + if (UI.domready) UI.Utils.checkDisplay(); + }); + + document.addEventListener('DOMContentLoaded', function(){ + + var domReady = function() { + + UI.$body = UI.$('body'); + + UI.ready(function(context){ + UI.domObserve('[data-uk-observe]'); + }); + + UI.on('changed.uk.dom', function(e) { + UI.init(e.target); + UI.Utils.checkDisplay(e.target); + }); + + UI.trigger('beforeready.uk.dom'); + + UI.component.bootComponents(); + + // custom scroll observer + requestAnimationFrame((function(){ + + var memory = {dir: {x:0, y:0}, x: window.pageXOffset, y:window.pageYOffset}; + + var fn = function(){ + // reading this (window.page[X|Y]Offset) causes a full page recalc of the layout in Chrome, + // so we only want to do this once + var wpxo = window.pageXOffset; + var wpyo = window.pageYOffset; + + // Did the scroll position change since the last time we were here? + if (memory.x != wpxo || memory.y != wpyo) { + + // Set the direction of the scroll and store the new position + if (wpxo != memory.x) {memory.dir.x = wpxo > memory.x ? 1:-1; } else { memory.dir.x = 0; } + if (wpyo != memory.y) {memory.dir.y = wpyo > memory.y ? 1:-1; } else { memory.dir.y = 0; } + + memory.x = wpxo; + memory.y = wpyo; + + // Trigger the scroll event, this could probably be sent using memory.clone() but this is + // more explicit and easier to see exactly what is being sent in the event. + UI.$doc.trigger('scrolling.uk.document', [{ + "dir": {"x": memory.dir.x, "y": memory.dir.y}, "x": wpxo, "y": wpyo + }]); + } + + requestAnimationFrame(fn); + }; + + if (UI.support.touch) { + UI.$html.on('touchmove touchend MSPointerMove MSPointerUp pointermove pointerup', fn); + } + + if (memory.x || memory.y) fn(); + + return fn; + + })()); + + // run component init functions on dom + UI.trigger('domready.uk.dom'); + + if (UI.support.touch) { + + // remove css hover rules for touch devices + // UI.Utils.removeCssRules(/\.uk-(?!navbar).*:hover/); + + // viewport unit fix for uk-height-viewport - should be fixed in iOS 8 + if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) { + + UI.$win.on('load orientationchange resize', UI.Utils.debounce((function(){ + + var fn = function() { + $('.uk-height-viewport').css('height', window.innerHeight); + return fn; + }; + + return fn(); + + })(), 100)); + } + } + + UI.trigger('afterready.uk.dom'); + + // mark that domready is left behind + UI.domready = true; + }; + + if (document.readyState == 'complete' || document.readyState == 'interactive') { + setTimeout(domReady); + } + + return domReady; + + }()); + + // add touch identifier class + UI.$html.addClass(UI.support.touch ? "uk-touch" : "uk-notouch"); + + // add uk-hover class on tap to support overlays on touch devices + if (UI.support.touch) { + + var hoverset = false, + exclude, + hovercls = 'uk-hover', + selector = '.uk-overlay, .uk-overlay-hover, .uk-overlay-toggle, .uk-animation-hover, .uk-has-hover'; + + UI.$html.on('mouseenter touchstart MSPointerDown pointerdown', selector, function() { + + if (hoverset) $('.'+hovercls).removeClass(hovercls); + + hoverset = $(this).addClass(hovercls); + + }).on('mouseleave touchend MSPointerUp pointerup', function(e) { + + exclude = $(e.target).parents(selector); + + if (hoverset) { + hoverset.not(exclude).removeClass(hovercls); + } + }); + } + + return UI; +}); + +// Based on Zeptos touch.js +// https://raw.github.com/madrobby/zepto/master/src/touch.js +// Zepto.js may be freely distributed under the MIT license. + +;(function($){ + + if ($.fn.swipeLeft) { + return; + } + + + var touch = {}, touchTimeout, tapTimeout, swipeTimeout, longTapTimeout, longTapDelay = 750, gesture; + + function swipeDirection(x1, x2, y1, y2) { + return Math.abs(x1 - x2) >= Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down'); + } + + function longTap() { + longTapTimeout = null; + if (touch.last) { + if ( touch.el !== undefined ) touch.el.trigger('longTap'); + touch = {}; + } + } + + function cancelLongTap() { + if (longTapTimeout) clearTimeout(longTapTimeout); + longTapTimeout = null; + } + + function cancelAll() { + if (touchTimeout) clearTimeout(touchTimeout); + if (tapTimeout) clearTimeout(tapTimeout); + if (swipeTimeout) clearTimeout(swipeTimeout); + if (longTapTimeout) clearTimeout(longTapTimeout); + touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null; + touch = {}; + } + + function isPrimaryTouch(event){ + return event.pointerType == event.MSPOINTER_TYPE_TOUCH && event.isPrimary; + } + + $(function(){ + var now, delta, deltaX = 0, deltaY = 0, firstTouch; + + if ('MSGesture' in window) { + gesture = new MSGesture(); + gesture.target = document.body; + } + + $(document) + .on('MSGestureEnd gestureend', function(e){ + + var swipeDirectionFromVelocity = e.originalEvent.velocityX > 1 ? 'Right' : e.originalEvent.velocityX < -1 ? 'Left' : e.originalEvent.velocityY > 1 ? 'Down' : e.originalEvent.velocityY < -1 ? 'Up' : null; + + if (swipeDirectionFromVelocity && touch.el !== undefined) { + touch.el.trigger('swipe'); + touch.el.trigger('swipe'+ swipeDirectionFromVelocity); + } + }) + // MSPointerDown: for IE10 + // pointerdown: for IE11 + .on('touchstart MSPointerDown pointerdown', function(e){ + + if(e.type == 'MSPointerDown' && !isPrimaryTouch(e.originalEvent)) return; + + firstTouch = (e.type == 'MSPointerDown' || e.type == 'pointerdown') ? e : e.originalEvent.touches[0]; + + now = Date.now(); + delta = now - (touch.last || now); + touch.el = $('tagName' in firstTouch.target ? firstTouch.target : firstTouch.target.parentNode); + + if(touchTimeout) clearTimeout(touchTimeout); + + touch.x1 = firstTouch.pageX; + touch.y1 = firstTouch.pageY; + + if (delta > 0 && delta <= 250) touch.isDoubleTap = true; + + touch.last = now; + longTapTimeout = setTimeout(longTap, longTapDelay); + + // adds the current touch contact for IE gesture recognition + if (gesture && ( e.type == 'MSPointerDown' || e.type == 'pointerdown' || e.type == 'touchstart' ) ) { + gesture.addPointer(e.originalEvent.pointerId); + } + + }) + // MSPointerMove: for IE10 + // pointermove: for IE11 + .on('touchmove MSPointerMove pointermove', function(e){ + + if (e.type == 'MSPointerMove' && !isPrimaryTouch(e.originalEvent)) return; + + firstTouch = (e.type == 'MSPointerMove' || e.type == 'pointermove') ? e : e.originalEvent.touches[0]; + + cancelLongTap(); + touch.x2 = firstTouch.pageX; + touch.y2 = firstTouch.pageY; + + deltaX += Math.abs(touch.x1 - touch.x2); + deltaY += Math.abs(touch.y1 - touch.y2); + }) + // MSPointerUp: for IE10 + // pointerup: for IE11 + .on('touchend MSPointerUp pointerup', function(e){ + + if (e.type == 'MSPointerUp' && !isPrimaryTouch(e.originalEvent)) return; + + cancelLongTap(); + + // swipe + if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) || (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)){ + + swipeTimeout = setTimeout(function() { + if ( touch.el !== undefined ) { + touch.el.trigger('swipe'); + touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2))); + } + touch = {}; + }, 0); + + // normal tap + } else if ('last' in touch) { + + // don't fire tap when delta position changed by more than 30 pixels, + // for instance when moving to a point and back to origin + if (isNaN(deltaX) || (deltaX < 30 && deltaY < 30)) { + // delay by one tick so we can cancel the 'tap' event if 'scroll' fires + // ('tap' fires before 'scroll') + tapTimeout = setTimeout(function() { + + // trigger universal 'tap' with the option to cancelTouch() + // (cancelTouch cancels processing of single vs double taps for faster 'tap' response) + var event = $.Event('tap'); + event.cancelTouch = cancelAll; + if ( touch.el !== undefined ) touch.el.trigger(event); + + // trigger double tap immediately + if (touch.isDoubleTap) { + if ( touch.el !== undefined ) touch.el.trigger('doubleTap'); + touch = {}; + } + + // trigger single tap after 250ms of inactivity + else { + touchTimeout = setTimeout(function(){ + touchTimeout = null; + if ( touch.el !== undefined ) touch.el.trigger('singleTap'); + touch = {}; + }, 250); + } + }, 0); + } else { + touch = {}; + } + deltaX = deltaY = 0; + } + }) + // when the browser window loses focus, + // for example when a modal dialog is shown, + // cancel all ongoing events + .on('touchcancel MSPointerCancel', cancelAll); + + // scrolling the window indicates intention of the user + // to scroll, not tap or swipe, so cancel all ongoing events + $(window).on('scroll', cancelAll); + }); + + ['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(eventName){ + $.fn[eventName] = function(callback){ return $(this).on(eventName, callback); }; + }); +})(jQuery); + +(function(UI) { + + "use strict"; + + var stacks = []; + + UI.component('stackMargin', { + + defaults: { + cls: 'uk-margin-small-top', + rowfirst: false + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-margin]", context).each(function() { + + var ele = UI.$(this); + + if (!ele.data("stackMargin")) { + UI.stackMargin(ele, UI.Utils.options(ele.attr("data-uk-margin"))); + } + }); + }); + }, + + init: function() { + + var $this = this; + + UI.$win.on('resize orientationchange', (function() { + + var fn = function() { + $this.process(); + }; + + UI.$(function() { + fn(); + UI.$win.on("load", fn); + }); + + return UI.Utils.debounce(fn, 20); + })()); + + UI.$html.on("changed.uk.dom", function(e) { + $this.process(); + }); + + this.on("display.uk.check", function(e) { + if (this.element.is(":visible")) this.process(); + }.bind(this)); + + stacks.push(this); + }, + + process: function() { + + var $this = this, columns = this.element.children(); + + UI.Utils.stackMargin(columns, this.options); + + if (!this.options.rowfirst) { + return this; + } + + // Mark first column elements + var pos_cache = columns.removeClass(this.options.rowfirst).filter(':visible').first().position(); + + if (pos_cache) { + columns.each(function() { + UI.$(this)[UI.$(this).position().left == pos_cache.left ? 'addClass':'removeClass']($this.options.rowfirst); + }); + } + + return this; + } + + }); + + + // responsive element e.g. iframes + + (function(){ + + var elements = [], check = function(ele) { + + if (!ele.is(':visible')) return; + + var width = ele.parent().width(), + iwidth = ele.data('width'), + ratio = (width / iwidth), + height = Math.floor(ratio * ele.data('height')); + + ele.css({'height': (width < iwidth) ? height : ele.data('height')}); + }; + + UI.component('responsiveElement', { + + defaults: {}, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("iframe.uk-responsive-width, [data-uk-responsive]", context).each(function() { + + var ele = UI.$(this), obj; + + if (!ele.data("responsiveElement")) { + obj = UI.responsiveElement(ele, {}); + } + }); + }); + }, + + init: function() { + + var ele = this.element; + + if (ele.attr('width') && ele.attr('height')) { + + ele.data({ + + 'width' : ele.attr('width'), + 'height': ele.attr('height') + + }).on('display.uk.check', function(){ + check(ele); + }); + + check(ele); + + elements.push(ele); + } + } + }); + + UI.$win.on('resize load', UI.Utils.debounce(function(){ + + elements.forEach(function(ele){ + check(ele); + }); + + }, 15)); + + })(); + + + + // helper + + UI.Utils.stackMargin = function(elements, options) { + + options = UI.$.extend({ + 'cls': 'uk-margin-small-top' + }, options); + + options.cls = options.cls; + + elements = UI.$(elements).removeClass(options.cls); + + var skip = false, + firstvisible = elements.filter(":visible:first"), + offset = firstvisible.length ? (firstvisible.position().top + firstvisible.outerHeight()) - 1 : false; // (-1): weird firefox bug when parent container is display:flex + + if (offset === false || elements.length == 1) return; + + elements.each(function() { + + var column = UI.$(this); + + if (column.is(":visible")) { + + if (skip) { + column.addClass(options.cls); + } else { + + if (column.position().top >= offset) { + skip = column.addClass(options.cls); + } + } + } + }); + }; + + UI.Utils.matchHeights = function(elements, options) { + + elements = UI.$(elements).css('min-height', ''); + options = UI.$.extend({ row : true }, options); + + var matchHeights = function(group){ + + if (group.length < 2) return; + + var max = 0; + + group.each(function() { + max = Math.max(max, UI.$(this).outerHeight()); + }).each(function() { + + var element = UI.$(this), + height = max - (element.css('box-sizing') == 'border-box' ? 0 : (element.outerHeight() - element.height())); + + element.css('min-height', height + 'px'); + }); + }; + + if (options.row) { + + elements.first().width(); // force redraw + + setTimeout(function(){ + + var lastoffset = false, group = []; + + elements.each(function() { + + var ele = UI.$(this), offset = ele.offset().top; + + if (offset != lastoffset && group.length) { + + matchHeights(UI.$(group)); + group = []; + offset = ele.offset().top; + } + + group.push(ele); + lastoffset = offset; + }); + + if (group.length) { + matchHeights(UI.$(group)); + } + + }, 0); + + } else { + matchHeights(elements); + } + }; + + (function(cacheSvgs){ + + UI.Utils.inlineSvg = function(selector, root) { + + var images = UI.$(selector || 'img[src$=".svg"]', root || document).each(function(){ + + var img = UI.$(this), + src = img.attr('src'); + + if (!cacheSvgs[src]) { + + var d = UI.$.Deferred(); + + UI.$.get(src, {nc: Math.random()}, function(data){ + d.resolve(UI.$(data).find('svg')); + }); + + cacheSvgs[src] = d.promise(); + } + + cacheSvgs[src].then(function(svg) { + + var $svg = UI.$(svg).clone(); + + if (img.attr('id')) $svg.attr('id', img.attr('id')); + if (img.attr('class')) $svg.attr('class', img.attr('class')); + if (img.attr('style')) $svg.attr('style', img.attr('style')); + + if (img.attr('width')) { + $svg.attr('width', img.attr('width')); + if (!img.attr('height')) $svg.removeAttr('height'); + } + + if (img.attr('height')){ + $svg.attr('height', img.attr('height')); + if (!img.attr('width')) $svg.removeAttr('width'); + } + + img.replaceWith($svg); + }); + }); + }; + + // init code + UI.ready(function(context) { + UI.Utils.inlineSvg('[data-uk-svg]', context); + }); + + })({}); + +})(UIkit); + +(function(UI) { + + "use strict"; + + UI.component('smoothScroll', { + + boot: function() { + + // init code + UI.$html.on("click.smooth-scroll.uikit", "[data-uk-smooth-scroll]", function(e) { + var ele = UI.$(this); + + if (!ele.data("smoothScroll")) { + var obj = UI.smoothScroll(ele, UI.Utils.options(ele.attr("data-uk-smooth-scroll"))); + ele.trigger("click"); + } + + return false; + }); + }, + + init: function() { + + var $this = this; + + this.on("click", function(e) { + e.preventDefault(); + scrollToElement(UI.$(this.hash).length ? UI.$(this.hash) : UI.$("body"), $this.options); + }); + } + }); + + function scrollToElement(ele, options) { + + options = UI.$.extend({ + duration: 1000, + transition: 'easeOutExpo', + offset: 0, + complete: function(){} + }, options); + + // get / set parameters + var target = ele.offset().top - options.offset, + docheight = UI.$doc.height(), + winheight = window.innerHeight; + + if ((target + winheight) > docheight) { + target = docheight - winheight; + } + + // animate to target, fire callback when done + UI.$("html,body").stop().animate({scrollTop: target}, options.duration, options.transition).promise().done(options.complete); + } + + UI.Utils.scrollToElement = scrollToElement; + + if (!UI.$.easing.easeOutExpo) { + UI.$.easing.easeOutExpo = function(x, t, b, c, d) { return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; }; + } + +})(UIkit); + +(function(UI) { + + "use strict"; + + var $win = UI.$win, + $doc = UI.$doc, + scrollspies = [], + checkScrollSpy = function() { + for(var i=0; i < scrollspies.length; i++) { + window.requestAnimationFrame.apply(window, [scrollspies[i].check]); + } + }; + + UI.component('scrollspy', { + + defaults: { + "target" : false, + "cls" : "uk-scrollspy-inview", + "initcls" : "uk-scrollspy-init-inview", + "topoffset" : 0, + "leftoffset" : 0, + "repeat" : false, + "delay" : 0 + }, + + boot: function() { + + // listen to scroll and resize + $doc.on("scrolling.uk.document", checkScrollSpy); + $win.on("load resize orientationchange", UI.Utils.debounce(checkScrollSpy, 50)); + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-scrollspy]", context).each(function() { + + var element = UI.$(this); + + if (!element.data("scrollspy")) { + var obj = UI.scrollspy(element, UI.Utils.options(element.attr("data-uk-scrollspy"))); + } + }); + }); + }, + + init: function() { + + var $this = this, inviewstate, initinview, togglecls = this.options.cls.split(/,/), fn = function(){ + + var elements = $this.options.target ? $this.element.find($this.options.target) : $this.element, + delayIdx = elements.length === 1 ? 1 : 0, + toggleclsIdx = 0; + + elements.each(function(idx){ + + var element = UI.$(this), + inviewstate = element.data('inviewstate'), + inview = UI.Utils.isInView(element, $this.options), + toggle = element.data('ukScrollspyCls') || togglecls[toggleclsIdx].trim(); + + if (inview && !inviewstate && !element.data('scrollspy-idle')) { + + if (!initinview) { + element.addClass($this.options.initcls); + $this.offset = element.offset(); + initinview = true; + + element.trigger("init.uk.scrollspy"); + } + + element.data('scrollspy-idle', setTimeout(function(){ + + element.addClass("uk-scrollspy-inview").toggleClass(toggle).width(); + element.trigger("inview.uk.scrollspy"); + + element.data('scrollspy-idle', false); + element.data('inviewstate', true); + + }, $this.options.delay * delayIdx)); + + delayIdx++; + } + + if (!inview && inviewstate && $this.options.repeat) { + + if (element.data('scrollspy-idle')) { + clearTimeout(element.data('scrollspy-idle')); + element.data('scrollspy-idle', false); + } + + element.removeClass("uk-scrollspy-inview").toggleClass(toggle); + element.data('inviewstate', false); + + element.trigger("outview.uk.scrollspy"); + } + + toggleclsIdx = togglecls[toggleclsIdx + 1] ? (toggleclsIdx + 1) : 0; + + }); + }; + + fn(); + + this.check = fn; + + scrollspies.push(this); + } + }); + + + var scrollspynavs = [], + checkScrollSpyNavs = function() { + for(var i=0; i < scrollspynavs.length; i++) { + window.requestAnimationFrame.apply(window, [scrollspynavs[i].check]); + } + }; + + UI.component('scrollspynav', { + + defaults: { + "cls" : 'uk-active', + "closest" : false, + "topoffset" : 0, + "leftoffset" : 0, + "smoothscroll" : false + }, + + boot: function() { + + // listen to scroll and resize + $doc.on("scrolling.uk.document", checkScrollSpyNavs); + $win.on("resize orientationchange", UI.Utils.debounce(checkScrollSpyNavs, 50)); + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-scrollspy-nav]", context).each(function() { + + var element = UI.$(this); + + if (!element.data("scrollspynav")) { + var obj = UI.scrollspynav(element, UI.Utils.options(element.attr("data-uk-scrollspy-nav"))); + } + }); + }); + }, + + init: function() { + + var ids = [], + links = this.find("a[href^='#']").each(function(){ if(this.getAttribute("href").trim()!=='#') ids.push(this.getAttribute("href")); }), + targets = UI.$(ids.join(",")), + + clsActive = this.options.cls, + clsClosest = this.options.closest || this.options.closest; + + var $this = this, inviews, fn = function(){ + + inviews = []; + + for (var i=0 ; i < targets.length ; i++) { + if (UI.Utils.isInView(targets.eq(i), $this.options)) { + inviews.push(targets.eq(i)); + } + } + + if (inviews.length) { + + var navitems, + scrollTop = $win.scrollTop(), + target = (function(){ + for(var i=0; i< inviews.length;i++){ + if(inviews[i].offset().top >= scrollTop){ + return inviews[i]; + } + } + })(); + + if (!target) return; + + if ($this.options.closest) { + links.blur().closest(clsClosest).removeClass(clsActive); + navitems = links.filter("a[href='#"+target.attr("id")+"']").closest(clsClosest).addClass(clsActive); + } else { + navitems = links.removeClass(clsActive).filter("a[href='#"+target.attr("id")+"']").addClass(clsActive); + } + + $this.element.trigger("inview.uk.scrollspynav", [target, navitems]); + } + }; + + if (this.options.smoothscroll && UI.smoothScroll) { + links.each(function(){ + UI.smoothScroll(this, $this.options.smoothscroll); + }); + } + + fn(); + + this.element.data("scrollspynav", this); + + this.check = fn; + scrollspynavs.push(this); + + } + }); + +})(UIkit); + +(function(UI){ + + "use strict"; + + var toggles = []; + + UI.component('toggle', { + + defaults: { + target : false, + cls : 'uk-hidden', + animation : false, + duration : 200 + }, + + boot: function(){ + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-toggle]", context).each(function() { + var ele = UI.$(this); + + if (!ele.data("toggle")) { + var obj = UI.toggle(ele, UI.Utils.options(ele.attr("data-uk-toggle"))); + } + }); + + setTimeout(function(){ + + toggles.forEach(function(toggle){ + toggle.getToggles(); + }); + + }, 0); + }); + }, + + init: function() { + + var $this = this; + + this.aria = (this.options.cls.indexOf('uk-hidden') !== -1); + + this.getToggles(); + + this.on("click", function(e) { + if ($this.element.is('a[href="#"]')) e.preventDefault(); + $this.toggle(); + }); + + toggles.push(this); + }, + + toggle: function() { + + if(!this.totoggle.length) return; + + if (this.options.animation && UI.support.animation) { + + var $this = this, animations = this.options.animation.split(','); + + if (animations.length == 1) { + animations[1] = animations[0]; + } + + animations[0] = animations[0].trim(); + animations[1] = animations[1].trim(); + + this.totoggle.css('animation-duration', this.options.duration+'ms'); + + this.totoggle.each(function(){ + + var ele = UI.$(this); + + if (ele.hasClass($this.options.cls)) { + + ele.toggleClass($this.options.cls); + + UI.Utils.animate(ele, animations[0]).then(function(){ + ele.css('animation-duration', ''); + UI.Utils.checkDisplay(ele); + }); + + } else { + + UI.Utils.animate(this, animations[1]+' uk-animation-reverse').then(function(){ + ele.toggleClass($this.options.cls).css('animation-duration', ''); + UI.Utils.checkDisplay(ele); + }); + + } + + }); + + } else { + this.totoggle.toggleClass(this.options.cls); + UI.Utils.checkDisplay(this.totoggle); + } + + this.updateAria(); + + }, + + getToggles: function() { + this.totoggle = this.options.target ? UI.$(this.options.target):[]; + this.updateAria(); + }, + + updateAria: function() { + if (this.aria && this.totoggle.length) { + this.totoggle.each(function(){ + UI.$(this).attr('aria-hidden', UI.$(this).hasClass('uk-hidden')); + }); + } + } + }); + +})(UIkit); + +(function(UI) { + + "use strict"; + + UI.component('alert', { + + defaults: { + "fade": true, + "duration": 200, + "trigger": ".uk-alert-close" + }, + + boot: function() { + + // init code + UI.$html.on("click.alert.uikit", "[data-uk-alert]", function(e) { + + var ele = UI.$(this); + + if (!ele.data("alert")) { + + var alert = UI.alert(ele, UI.Utils.options(ele.attr("data-uk-alert"))); + + if (UI.$(e.target).is(alert.options.trigger)) { + e.preventDefault(); + alert.close(); + } + } + }); + }, + + init: function() { + + var $this = this; + + this.on("click", this.options.trigger, function(e) { + e.preventDefault(); + $this.close(); + }); + }, + + close: function() { + + var element = this.trigger("close.uk.alert"), + removeElement = function () { + this.trigger("closed.uk.alert").remove(); + }.bind(this); + + if (this.options.fade) { + element.css("overflow", "hidden").css("max-height", element.height()).animate({ + "height" : 0, + "opacity" : 0, + "padding-top" : 0, + "padding-bottom" : 0, + "margin-top" : 0, + "margin-bottom" : 0 + }, this.options.duration, removeElement); + } else { + removeElement(); + } + } + + }); + +})(UIkit); + +(function(UI) { + + "use strict"; + + UI.component('buttonRadio', { + + defaults: { + "activeClass": 'uk-active', + "target": ".uk-button" + }, + + boot: function() { + + // init code + UI.$html.on("click.buttonradio.uikit", "[data-uk-button-radio]", function(e) { + + var ele = UI.$(this); + + if (!ele.data("buttonRadio")) { + + var obj = UI.buttonRadio(ele, UI.Utils.options(ele.attr("data-uk-button-radio"))), + target = UI.$(e.target); + + if (target.is(obj.options.target)) { + target.trigger("click"); + } + } + }); + }, + + init: function() { + + var $this = this; + + // Init ARIA + this.find($this.options.target).attr('aria-checked', 'false').filter('.' + $this.options.activeClass).attr('aria-checked', 'true'); + + this.on("click", this.options.target, function(e) { + + var ele = UI.$(this); + + if (ele.is('a[href="#"]')) e.preventDefault(); + + $this.find($this.options.target).not(ele).removeClass($this.options.activeClass).blur(); + ele.addClass($this.options.activeClass); + + // Update ARIA + $this.find($this.options.target).not(ele).attr('aria-checked', 'false'); + ele.attr('aria-checked', 'true'); + + $this.trigger("change.uk.button", [ele]); + }); + + }, + + getSelected: function() { + return this.find('.' + this.options.activeClass); + } + }); + + UI.component('buttonCheckbox', { + + defaults: { + "activeClass": 'uk-active', + "target": ".uk-button" + }, + + boot: function() { + + UI.$html.on("click.buttoncheckbox.uikit", "[data-uk-button-checkbox]", function(e) { + var ele = UI.$(this); + + if (!ele.data("buttonCheckbox")) { + + var obj = UI.buttonCheckbox(ele, UI.Utils.options(ele.attr("data-uk-button-checkbox"))), + target = UI.$(e.target); + + if (target.is(obj.options.target)) { + target.trigger("click"); + } + } + }); + }, + + init: function() { + + var $this = this; + + // Init ARIA + this.find($this.options.target).attr('aria-checked', 'false').filter('.' + $this.options.activeClass).attr('aria-checked', 'true'); + + this.on("click", this.options.target, function(e) { + var ele = UI.$(this); + + if (ele.is('a[href="#"]')) e.preventDefault(); + + ele.toggleClass($this.options.activeClass).blur(); + + // Update ARIA + ele.attr('aria-checked', ele.hasClass($this.options.activeClass)); + + $this.trigger("change.uk.button", [ele]); + }); + + }, + + getSelected: function() { + return this.find('.' + this.options.activeClass); + } + }); + + + UI.component('button', { + + defaults: {}, + + boot: function() { + + UI.$html.on("click.button.uikit", "[data-uk-button]", function(e) { + var ele = UI.$(this); + + if (!ele.data("button")) { + + var obj = UI.button(ele, UI.Utils.options(ele.attr("data-uk-button"))); + ele.trigger("click"); + } + }); + }, + + init: function() { + + var $this = this; + + // Init ARIA + this.element.attr('aria-pressed', this.element.hasClass("uk-active")); + + this.on("click", function(e) { + + if ($this.element.is('a[href="#"]')) e.preventDefault(); + + $this.toggle(); + $this.trigger("change.uk.button", [$this.element.blur().hasClass("uk-active")]); + }); + + }, + + toggle: function() { + this.element.toggleClass("uk-active"); + + // Update ARIA + this.element.attr('aria-pressed', this.element.hasClass("uk-active")); + } + }); + +})(UIkit); + + +(function(UI) { + + "use strict"; + + var active = false, hoverIdle, flips = { + 'x': { + "bottom-left" : 'bottom-right', + "bottom-right" : 'bottom-left', + "bottom-center" : 'bottom-center', + "top-left" : 'top-right', + "top-right" : 'top-left', + "top-center" : 'top-center', + "left-top" : 'right-top', + "left-bottom" : 'right-bottom', + "left-center" : 'right-center', + "right-top" : 'left-top', + "right-bottom" : 'left-bottom', + "right-center" : 'left-center' + }, + 'y': { + "bottom-left" : 'top-left', + "bottom-right" : 'top-right', + "bottom-center" : 'top-center', + "top-left" : 'bottom-left', + "top-right" : 'bottom-right', + "top-center" : 'bottom-center', + "left-top" : 'left-bottom', + "left-bottom" : 'left-top', + "left-center" : 'left-center', + "right-top" : 'right-bottom', + "right-bottom" : 'right-top', + "right-center" : 'right-center' + }, + 'xy': { + "bottom-left" : 'top-right', + "bottom-right" : 'top-left', + "bottom-center" : 'top-center', + "top-left" : 'bottom-right', + "top-right" : 'bottom-left', + "top-center" : 'bottom-center', + "left-top" : 'right-bottom', + "left-bottom" : 'right-top', + "left-center" : 'right-center', + "right-top" : 'left-bottom', + "right-bottom" : 'left-top', + "right-center" : 'left-center' + } + }; + + UI.component('dropdown', { + + defaults: { + 'mode' : 'hover', + 'pos' : 'bottom-left', + 'offset' : 0, + 'remaintime' : 800, + 'justify' : false, + 'boundary' : UI.$win, + 'delay' : 0, + 'dropdownSelector': '.uk-dropdown,.uk-dropdown-blank', + 'hoverDelayIdle' : 250, + 'preventflip' : false + }, + + remainIdle: false, + + boot: function() { + + var triggerevent = UI.support.touch ? "click" : "mouseenter"; + + // init code + UI.$html.on(triggerevent+".dropdown.uikit", "[data-uk-dropdown]", function(e) { + + var ele = UI.$(this); + + if (!ele.data("dropdown")) { + + var dropdown = UI.dropdown(ele, UI.Utils.options(ele.attr("data-uk-dropdown"))); + + if (triggerevent=="click" || (triggerevent=="mouseenter" && dropdown.options.mode=="hover")) { + dropdown.element.trigger(triggerevent); + } + + if (dropdown.element.find(dropdown.options.dropdownSelector).length) { + e.preventDefault(); + } + } + }); + }, + + init: function() { + + var $this = this; + + this.dropdown = this.find(this.options.dropdownSelector); + this.offsetParent = this.dropdown.parents().filter(function() { + return UI.$.inArray(UI.$(this).css('position'), ['relative', 'fixed', 'absolute']) !== -1; + }).slice(0,1); + + this.centered = this.dropdown.hasClass('uk-dropdown-center'); + this.justified = this.options.justify ? UI.$(this.options.justify) : false; + + this.boundary = UI.$(this.options.boundary); + + if (!this.boundary.length) { + this.boundary = UI.$win; + } + + // legacy DEPRECATED! + if (this.dropdown.hasClass('uk-dropdown-up')) { + this.options.pos = 'top-left'; + } + if (this.dropdown.hasClass('uk-dropdown-flip')) { + this.options.pos = this.options.pos.replace('left','right'); + } + if (this.dropdown.hasClass('uk-dropdown-center')) { + this.options.pos = this.options.pos.replace(/(left|right)/,'center'); + } + //-- end legacy + + // Init ARIA + this.element.attr('aria-haspopup', 'true'); + this.element.attr('aria-expanded', this.element.hasClass("uk-open")); + + if (this.options.mode == "click" || UI.support.touch) { + + this.on("click.uk.dropdown", function(e) { + + var $target = UI.$(e.target); + + if (!$target.parents($this.options.dropdownSelector).length) { + + if ($target.is("a[href='#']") || $target.parent().is("a[href='#']") || ($this.dropdown.length && !$this.dropdown.is(":visible")) ){ + e.preventDefault(); + } + + $target.blur(); + } + + if (!$this.element.hasClass('uk-open')) { + + $this.show(); + + } else { + + if (!$this.dropdown.find(e.target).length || $target.is(".uk-dropdown-close") || $target.parents(".uk-dropdown-close").length) { + $this.hide(); + } + } + }); + + } else { + + this.on("mouseenter", function(e) { + + $this.trigger('pointerenter.uk.dropdown', [$this]); + + if ($this.remainIdle) { + clearTimeout($this.remainIdle); + } + + if (hoverIdle) { + clearTimeout(hoverIdle); + } + + if (active && active == $this) { + return; + } + + // pseudo manuAim + if (active && active != $this) { + + hoverIdle = setTimeout(function() { + hoverIdle = setTimeout($this.show.bind($this), $this.options.delay); + }, $this.options.hoverDelayIdle); + + } else { + + hoverIdle = setTimeout($this.show.bind($this), $this.options.delay); + } + + }).on("mouseleave", function() { + + if (hoverIdle) { + clearTimeout(hoverIdle); + } + + $this.remainIdle = setTimeout(function() { + if (active && active == $this) $this.hide(); + }, $this.options.remaintime); + + $this.trigger('pointerleave.uk.dropdown', [$this]); + + }).on("click", function(e){ + + var $target = UI.$(e.target); + + if ($this.remainIdle) { + clearTimeout($this.remainIdle); + } + + if (active && active == $this) { + if (!$this.dropdown.find(e.target).length || $target.is(".uk-dropdown-close") || $target.parents(".uk-dropdown-close").length) { + $this.hide(); + } + return; + } + + if ($target.is("a[href='#']") || $target.parent().is("a[href='#']")){ + e.preventDefault(); + } + + $this.show(); + }); + } + }, + + show: function(){ + + UI.$html.off("click.outer.dropdown"); + + if (active && active != this) { + active.hide(true); + } + + if (hoverIdle) { + clearTimeout(hoverIdle); + } + + this.trigger('beforeshow.uk.dropdown', [this]); + + this.checkDimensions(); + this.element.addClass('uk-open'); + + // Update ARIA + this.element.attr('aria-expanded', 'true'); + + this.trigger('show.uk.dropdown', [this]); + + UI.Utils.checkDisplay(this.dropdown, true); + active = this; + + this.registerOuterClick(); + }, + + hide: function(force) { + + this.trigger('beforehide.uk.dropdown', [this, force]); + + this.element.removeClass('uk-open'); + + if (this.remainIdle) { + clearTimeout(this.remainIdle); + } + + this.remainIdle = false; + + // Update ARIA + this.element.attr('aria-expanded', 'false'); + + this.trigger('hide.uk.dropdown', [this, force]); + + if (active == this) active = false; + }, + + registerOuterClick: function(){ + + var $this = this; + + UI.$html.off("click.outer.dropdown"); + + setTimeout(function() { + + UI.$html.on("click.outer.dropdown", function(e) { + + if (hoverIdle) { + clearTimeout(hoverIdle); + } + + var $target = UI.$(e.target); + + if (active == $this && !$this.element.find(e.target).length) { + $this.hide(true); + UI.$html.off("click.outer.dropdown"); + } + }); + }, 10); + }, + + checkDimensions: function() { + + if (!this.dropdown.length) return; + + // reset + this.dropdown.removeClass('uk-dropdown-top uk-dropdown-bottom uk-dropdown-left uk-dropdown-right uk-dropdown-stack').css({ + 'top-left':'', + 'left':'', + 'margin-left' :'', + 'margin-right':'' + }); + + if (this.justified && this.justified.length) { + this.dropdown.css("min-width", ""); + } + + var $this = this, + pos = UI.$.extend({}, this.offsetParent.offset(), {width: this.offsetParent[0].offsetWidth, height: this.offsetParent[0].offsetHeight}), + posoffset = this.options.offset, + dropdown = this.dropdown, + offset = dropdown.show().offset() || {left: 0, top: 0}, + width = dropdown.outerWidth(), + height = dropdown.outerHeight(), + boundarywidth = this.boundary.width(), + boundaryoffset = this.boundary[0] !== window && this.boundary.offset() ? this.boundary.offset(): {top:0, left:0}, + dpos = this.options.pos; + + var variants = { + "bottom-left" : {top: 0 + pos.height + posoffset, left: 0}, + "bottom-right" : {top: 0 + pos.height + posoffset, left: 0 + pos.width - width}, + "bottom-center" : {top: 0 + pos.height + posoffset, left: 0 + pos.width / 2 - width / 2}, + "top-left" : {top: 0 - height - posoffset, left: 0}, + "top-right" : {top: 0 - height - posoffset, left: 0 + pos.width - width}, + "top-center" : {top: 0 - height - posoffset, left: 0 + pos.width / 2 - width / 2}, + "left-top" : {top: 0, left: 0 - width - posoffset}, + "left-bottom" : {top: 0 + pos.height - height, left: 0 - width - posoffset}, + "left-center" : {top: 0 + pos.height / 2 - height / 2, left: 0 - width - posoffset}, + "right-top" : {top: 0, left: 0 + pos.width + posoffset}, + "right-bottom" : {top: 0 + pos.height - height, left: 0 + pos.width + posoffset}, + "right-center" : {top: 0 + pos.height / 2 - height / 2, left: 0 + pos.width + posoffset} + }, + css = {}, + pp; + + pp = dpos.split('-'); + css = variants[dpos] ? variants[dpos] : variants['bottom-left']; + + // justify dropdown + if (this.justified && this.justified.length) { + justify(dropdown.css({left:0}), this.justified, boundarywidth); + } else { + + if (this.options.preventflip !== true) { + + var fdpos; + + switch(this.checkBoundary(pos.left + css.left, pos.top + css.top, width, height, boundarywidth)) { + case "x": + if(this.options.preventflip !=='x') fdpos = flips['x'][dpos] || 'right-top'; + break; + case "y": + if(this.options.preventflip !=='y') fdpos = flips['y'][dpos] || 'top-left'; + break; + case "xy": + if(!this.options.preventflip) fdpos = flips['xy'][dpos] || 'right-bottom'; + break; + } + + if (fdpos) { + + pp = fdpos.split('-'); + css = variants[fdpos] ? variants[fdpos] : variants['bottom-left']; + + // check flipped + if (this.checkBoundary(pos.left + css.left, pos.top + css.top, width, height, boundarywidth)) { + pp = dpos.split('-'); + css = variants[dpos] ? variants[dpos] : variants['bottom-left']; + } + } + } + } + + if (width > boundarywidth) { + dropdown.addClass("uk-dropdown-stack"); + this.trigger('stack.uk.dropdown', [this]); + } + + dropdown.css(css).css("display", "").addClass('uk-dropdown-'+pp[0]); + }, + + checkBoundary: function(left, top, width, height, boundarywidth) { + + var axis = ""; + + if (left < 0 || ((left - UI.$win.scrollLeft())+width) > boundarywidth) { + axis += "x"; + } + + if ((top - UI.$win.scrollTop()) < 0 || ((top - UI.$win.scrollTop())+height) > window.innerHeight) { + axis += "y"; + } + + return axis; + } + }); + + + UI.component('dropdownOverlay', { + + defaults: { + 'justify' : false, + 'cls' : '', + 'duration': 200 + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-dropdown-overlay]", context).each(function() { + var ele = UI.$(this); + + if (!ele.data("dropdownOverlay")) { + UI.dropdownOverlay(ele, UI.Utils.options(ele.attr("data-uk-dropdown-overlay"))); + } + }); + }); + }, + + init: function() { + + var $this = this; + + this.justified = this.options.justify ? UI.$(this.options.justify) : false; + this.overlay = this.element.find('uk-dropdown-overlay'); + + if (!this.overlay.length) { + this.overlay = UI.$('<div class="uk-dropdown-overlay"></div>').appendTo(this.element); + } + + this.overlay.addClass(this.options.cls); + + this.on({ + + 'beforeshow.uk.dropdown': function(e, dropdown) { + $this.dropdown = dropdown; + + if ($this.justified && $this.justified.length) { + justify($this.overlay.css({'display':'block', 'margin-left':'','margin-right':''}), $this.justified, $this.justified.outerWidth()); + } + }, + + 'show.uk.dropdown': function(e, dropdown) { + + var h = $this.dropdown.dropdown.outerHeight(true); + + $this.dropdown.element.removeClass('uk-open'); + + $this.overlay.stop().css('display', 'block').animate({height: h}, $this.options.duration, function() { + + $this.dropdown.dropdown.css('visibility', ''); + $this.dropdown.element.addClass('uk-open'); + + UI.Utils.checkDisplay($this.dropdown.dropdown, true); + }); + + $this.pointerleave = false; + }, + + 'hide.uk.dropdown': function() { + $this.overlay.stop().animate({height: 0}, $this.options.duration); + }, + + 'pointerenter.uk.dropdown': function(e, dropdown) { + clearTimeout($this.remainIdle); + }, + + 'pointerleave.uk.dropdown': function(e, dropdown) { + $this.pointerleave = true; + } + }); + + + this.overlay.on({ + + 'mouseenter': function() { + if ($this.remainIdle) { + clearTimeout($this.dropdown.remainIdle); + clearTimeout($this.remainIdle); + } + }, + + 'mouseleave': function(){ + + if ($this.pointerleave && active) { + + $this.remainIdle = setTimeout(function() { + if(active) active.hide(); + }, active.options.remaintime); + } + } + }) + } + + }); + + + function justify(ele, justifyTo, boundarywidth, offset) { + + ele = UI.$(ele); + justifyTo = UI.$(justifyTo); + boundarywidth = boundarywidth || window.innerWidth; + offset = offset || ele.offset(); + + if (justifyTo.length) { + + var jwidth = justifyTo.outerWidth(); + + ele.css("min-width", jwidth); + + if (UI.langdirection == 'right') { + + var right1 = boundarywidth - (justifyTo.offset().left + jwidth), + right2 = boundarywidth - (ele.offset().left + ele.outerWidth()); + + ele.css("margin-right", right1 - right2); + + } else { + ele.css("margin-left", justifyTo.offset().left - offset.left); + } + } + } + +})(UIkit); + +(function(UI) { + + "use strict"; + + var grids = []; + + UI.component('gridMatchHeight', { + + defaults: { + "target" : false, + "row" : true, + "ignorestacked" : false + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-grid-match]", context).each(function() { + var grid = UI.$(this), obj; + + if (!grid.data("gridMatchHeight")) { + obj = UI.gridMatchHeight(grid, UI.Utils.options(grid.attr("data-uk-grid-match"))); + } + }); + }); + }, + + init: function() { + + var $this = this; + + this.columns = this.element.children(); + this.elements = this.options.target ? this.find(this.options.target) : this.columns; + + if (!this.columns.length) return; + + UI.$win.on('load resize orientationchange', (function() { + + var fn = function() { + $this.match(); + }; + + UI.$(function() { fn(); }); + + return UI.Utils.debounce(fn, 50); + })()); + + UI.$html.on("changed.uk.dom", function(e) { + $this.columns = $this.element.children(); + $this.elements = $this.options.target ? $this.find($this.options.target) : $this.columns; + $this.match(); + }); + + this.on("display.uk.check", function(e) { + if(this.element.is(":visible")) this.match(); + }.bind(this)); + + grids.push(this); + }, + + match: function() { + + var firstvisible = this.columns.filter(":visible:first"); + + if (!firstvisible.length) return; + + var stacked = Math.ceil(100 * parseFloat(firstvisible.css('width')) / parseFloat(firstvisible.parent().css('width'))) >= 100; + + if (stacked && !this.options.ignorestacked) { + this.revert(); + } else { + UI.Utils.matchHeights(this.elements, this.options); + } + + return this; + }, + + revert: function() { + this.elements.css('min-height', ''); + return this; + } + }); + + UI.component('gridMargin', { + + defaults: { + cls : 'uk-grid-margin', + rowfirst : 'uk-row-first' + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-grid-margin]", context).each(function() { + var grid = UI.$(this), obj; + + if (!grid.data("gridMargin")) { + obj = UI.gridMargin(grid, UI.Utils.options(grid.attr("data-uk-grid-margin"))); + } + }); + }); + }, + + init: function() { + + var stackMargin = UI.stackMargin(this.element, this.options); + } + }); + +})(UIkit); + +(function(UI) { + + "use strict"; + + var active = false, activeCount = 0, $html = UI.$html, body; + + UI.component('modal', { + + defaults: { + keyboard: true, + bgclose: true, + minScrollHeight: 150, + center: false, + modal: true + }, + + scrollable: false, + transition: false, + hasTransitioned: true, + + init: function() { + + if (!body) body = UI.$('body'); + + if (!this.element.length) return; + + var $this = this; + + this.paddingdir = "padding-" + (UI.langdirection == 'left' ? "right":"left"); + this.dialog = this.find(".uk-modal-dialog"); + + this.active = false; + + // Update ARIA + this.element.attr('aria-hidden', this.element.hasClass("uk-open")); + + this.on("click", ".uk-modal-close", function(e) { + e.preventDefault(); + $this.hide(); + }).on("click", function(e) { + + var target = UI.$(e.target); + + if (target[0] == $this.element[0] && $this.options.bgclose) { + $this.hide(); + } + }); + }, + + toggle: function() { + return this[this.isActive() ? "hide" : "show"](); + }, + + show: function() { + + if (!this.element.length) return; + + var $this = this; + + if (this.isActive()) return; + + if (this.options.modal && active) { + active.hide(true); + } + + this.element.removeClass("uk-open").show(); + this.resize(); + + if (this.options.modal) { + active = this; + } + + this.active = true; + + activeCount++; + + if (UI.support.transition) { + this.hasTransitioned = false; + this.element.one(UI.support.transition.end, function(){ + $this.hasTransitioned = true; + }).addClass("uk-open"); + } else { + this.element.addClass("uk-open"); + } + + $html.addClass("uk-modal-page").height(); // force browser engine redraw + + // Update ARIA + this.element.attr('aria-hidden', 'false'); + + this.element.trigger("show.uk.modal"); + + UI.Utils.checkDisplay(this.dialog, true); + + return this; + }, + + hide: function(force) { + + if (!force && UI.support.transition && this.hasTransitioned) { + + var $this = this; + + this.one(UI.support.transition.end, function() { + $this._hide(); + }).removeClass("uk-open"); + + } else { + + this._hide(); + } + + return this; + }, + + resize: function() { + + var bodywidth = body.width(); + + this.scrollbarwidth = window.innerWidth - bodywidth; + + body.css(this.paddingdir, this.scrollbarwidth); + + this.element.css('overflow-y', this.scrollbarwidth ? 'scroll' : 'auto'); + + if (!this.updateScrollable() && this.options.center) { + + var dh = this.dialog.outerHeight(), + pad = parseInt(this.dialog.css('margin-top'), 10) + parseInt(this.dialog.css('margin-bottom'), 10); + + if ((dh + pad) < window.innerHeight) { + this.dialog.css({'top': (window.innerHeight/2 - dh/2) - pad }); + } else { + this.dialog.css({'top': ''}); + } + } + }, + + updateScrollable: function() { + + // has scrollable? + var scrollable = this.dialog.find('.uk-overflow-container:visible:first'); + + if (scrollable.length) { + + scrollable.css('height', 0); + + var offset = Math.abs(parseInt(this.dialog.css('margin-top'), 10)), + dh = this.dialog.outerHeight(), + wh = window.innerHeight, + h = wh - 2*(offset < 20 ? 20:offset) - dh; + + scrollable.css({ + 'max-height': (h < this.options.minScrollHeight ? '':h), + 'height':'' + }); + + return true; + } + + return false; + }, + + _hide: function() { + + this.active = false; + if (activeCount > 0) activeCount--; + else activeCount = 0; + + this.element.hide().removeClass('uk-open'); + + // Update ARIA + this.element.attr('aria-hidden', 'true'); + + if (!activeCount) { + $html.removeClass('uk-modal-page'); + body.css(this.paddingdir, ""); + } + + if(active===this) active = false; + + this.trigger('hide.uk.modal'); + }, + + isActive: function() { + return this.active; + } + + }); + + UI.component('modalTrigger', { + + boot: function() { + + // init code + UI.$html.on("click.modal.uikit", "[data-uk-modal]", function(e) { + + var ele = UI.$(this); + + if (ele.is("a")) { + e.preventDefault(); + } + + if (!ele.data("modalTrigger")) { + var modal = UI.modalTrigger(ele, UI.Utils.options(ele.attr("data-uk-modal"))); + modal.show(); + } + + }); + + // close modal on esc button + UI.$html.on('keydown.modal.uikit', function (e) { + + if (active && e.keyCode === 27 && active.options.keyboard) { // ESC + e.preventDefault(); + active.hide(); + } + }); + + UI.$win.on("resize orientationchange", UI.Utils.debounce(function(){ + if (active) active.resize(); + }, 150)); + }, + + init: function() { + + var $this = this; + + this.options = UI.$.extend({ + "target": $this.element.is("a") ? $this.element.attr("href") : false + }, this.options); + + this.modal = UI.modal(this.options.target, this.options); + + this.on("click", function(e) { + e.preventDefault(); + $this.show(); + }); + + //methods + this.proxy(this.modal, "show hide isActive"); + } + }); + + UI.modal.dialog = function(content, options) { + + var modal = UI.modal(UI.$(UI.modal.dialog.template).appendTo("body"), options); + + modal.on("hide.uk.modal", function(){ + if (modal.persist) { + modal.persist.appendTo(modal.persist.data("modalPersistParent")); + modal.persist = false; + } + modal.element.remove(); + }); + + setContent(content, modal); + + return modal; + }; + + UI.modal.dialog.template = '<div class="uk-modal"><div class="uk-modal-dialog" style="min-height:0;"></div></div>'; + + UI.modal.alert = function(content, options) { + + options = UI.$.extend(true, {bgclose:false, keyboard:false, modal:false, labels:UI.modal.labels}, options); + + var modal = UI.modal.dialog(([ + '<div class="uk-margin uk-modal-content">'+String(content)+'</div>', + '<div class="uk-modal-footer uk-text-right"><button class="uk-button uk-button-primary uk-modal-close">'+options.labels.Ok+'</button></div>' + ]).join(""), options); + + modal.on('show.uk.modal', function(){ + setTimeout(function(){ + modal.element.find('button:first').focus(); + }, 50); + }); + + return modal.show(); + }; + + UI.modal.confirm = function(content, onconfirm, oncancel) { + + var options = arguments.length > 1 && arguments[arguments.length-1] ? arguments[arguments.length-1] : {}; + + onconfirm = UI.$.isFunction(onconfirm) ? onconfirm : function(){}; + oncancel = UI.$.isFunction(oncancel) ? oncancel : function(){}; + options = UI.$.extend(true, {bgclose:false, keyboard:false, modal:false, labels:UI.modal.labels}, UI.$.isFunction(options) ? {}:options); + + var modal = UI.modal.dialog(([ + '<div class="uk-margin uk-modal-content">'+String(content)+'</div>', + '<div class="uk-modal-footer uk-text-right"><button class="uk-button js-modal-confirm-cancel">'+options.labels.Cancel+'</button> <button class="uk-button uk-button-primary js-modal-confirm">'+options.labels.Ok+'</button></div>' + ]).join(""), options); + + modal.element.find(".js-modal-confirm, .js-modal-confirm-cancel").on("click", function(){ + UI.$(this).is('.js-modal-confirm') ? onconfirm() : oncancel(); + modal.hide(); + }); + + modal.on('show.uk.modal', function(){ + setTimeout(function(){ + modal.element.find('.js-modal-confirm').focus(); + }, 50); + }); + + return modal.show(); + }; + + UI.modal.prompt = function(text, value, onsubmit, options) { + + onsubmit = UI.$.isFunction(onsubmit) ? onsubmit : function(value){}; + options = UI.$.extend(true, {bgclose:false, keyboard:false, modal:false, labels:UI.modal.labels}, options); + + var modal = UI.modal.dialog(([ + text ? '<div class="uk-modal-content uk-form">'+String(text)+'</div>':'', + '<div class="uk-margin-small-top uk-modal-content uk-form"><p><input type="text" class="uk-width-1-1"></p></div>', + '<div class="uk-modal-footer uk-text-right"><button class="uk-button uk-modal-close">'+options.labels.Cancel+'</button> <button class="uk-button uk-button-primary js-modal-ok">'+options.labels.Ok+'</button></div>' + ]).join(""), options), + + input = modal.element.find("input[type='text']").val(value || '').on('keyup', function(e){ + if (e.keyCode == 13) { + modal.element.find(".js-modal-ok").trigger('click'); + } + }); + + modal.element.find(".js-modal-ok").on("click", function(){ + if (onsubmit(input.val())!==false){ + modal.hide(); + } + }); + + modal.on('show.uk.modal', function(){ + setTimeout(function(){ + input.focus(); + }, 50); + }); + + return modal.show(); + }; + + UI.modal.blockUI = function(content, options) { + + var modal = UI.modal.dialog(([ + '<div class="uk-margin uk-modal-content">'+String(content || '<div class="uk-text-center">...</div>')+'</div>' + ]).join(""), UI.$.extend({bgclose:false, keyboard:false, modal:false}, options)); + + modal.content = modal.element.find('.uk-modal-content:first'); + + return modal.show(); + }; + + + UI.modal.labels = { + 'Ok': 'Ok', + 'Cancel': 'Cancel' + }; + + + // helper functions + function setContent(content, modal){ + + if(!modal) return; + + if (typeof content === 'object') { + + // convert DOM object to a jQuery object + content = content instanceof jQuery ? content : UI.$(content); + + if(content.parent().length) { + modal.persist = content; + modal.persist.data("modalPersistParent", content.parent()); + } + }else if (typeof content === 'string' || typeof content === 'number') { + // just insert the data as innerHTML + content = UI.$('<div></div>').html(content); + }else { + // unsupported data type! + content = UI.$('<div></div>').html('UIkit.modal Error: Unsupported data type: ' + typeof content); + } + + content.appendTo(modal.element.find('.uk-modal-dialog')); + + return modal; + } + +})(UIkit); + +(function(UI) { + + "use strict"; + // navigation + UI.component('nav', { + + defaults: { + "toggle": ">li.uk-parent > a[href*='#']", + "lists": ">li.uk-parent > ul", + "multiple": true + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-nav]", context).each(function() { + var nav = UI.$(this); + + if (!nav.data("nav")) { + var obj = UI.nav(nav, UI.Utils.options(nav.attr("data-uk-nav"))); + } + }); + }); + }, + + init: function() { + + var $this = this; + + this.on("click.uk.nav", this.options.toggle, function(e) { + // e.preventDefault(); + var ele = UI.$(this); + $this.open(ele.parent()[0] == $this.element[0] ? ele : ele.parent("li")); + }); + + this.find(this.options.lists).each(function() { + var $ele = UI.$(this), + parent = $ele.parent(), + active = parent.hasClass("uk-active"); + + $ele.wrap('<div style="overflow:hidden;height:0;position:relative;"></div>'); + parent.data("list-container", $ele.parent()[active ? 'removeClass':'addClass']('uk-hidden')); + + // Init ARIA + parent.attr('aria-expanded', parent.hasClass("uk-open")); + + if (active) $this.open(parent, true); + }); + + }, + + open: function(li, noanimation) { + noanimation = true; + var $this = this, element = this.element, $li = UI.$(li), $container = $li.data('list-container'); + + if (!this.options.multiple) { + + element.children('.uk-open').not(li).each(function() { + + var ele = UI.$(this); + + if (ele.data('list-container')) { + ele.data('list-container').stop().animate({height: 0}, function() { + UI.$(this).parent().removeClass('uk-open').end().addClass('uk-hidden'); + }); + } + }); + } + + $li.toggleClass('uk-open'); + + // Update ARIA + $li.attr('aria-expanded', $li.hasClass('uk-open')); + + if ($container) { + + if ($li.hasClass('uk-open')) { + $container.removeClass('uk-hidden'); + } + + if (noanimation) { + + $container.stop().height($li.hasClass('uk-open') ? 'auto' : 0); + + if (!$li.hasClass('uk-open')) { + $container.addClass('uk-hidden'); + } + + this.trigger('display.uk.check'); + + } else { + + $container.stop().animate({ + height: ($li.hasClass('uk-open') ? getHeight($container.find('ul:first')) : 0) + }, function() { + + if (!$li.hasClass('uk-open')) { + $container.addClass('uk-hidden'); + } else { + $container.css('height', ''); + } + + $this.trigger('display.uk.check'); + }); + } + } + } + }); + + + // helper + + function getHeight(ele) { + var $ele = UI.$(ele), height = "auto"; + + if ($ele.is(":visible")) { + height = $ele.outerHeight(); + } else { + var tmp = { + position: $ele.css("position"), + visibility: $ele.css("visibility"), + display: $ele.css("display") + }; + + height = $ele.css({position: 'absolute', visibility: 'hidden', display: 'block'}).outerHeight(); + + $ele.css(tmp); // reset element + } + + return height; + } + +})(UIkit); + +(function(UI) { + + "use strict"; + + var scrollpos = {x: window.scrollX, y: window.scrollY}, + $win = UI.$win, + $doc = UI.$doc, + $html = UI.$html, + Offcanvas = { + + show: function(element) { + + element = UI.$(element); + + if (!element.length) return; + + var $body = UI.$('body'), + bar = element.find(".uk-offcanvas-bar:first"), + rtl = (UI.langdirection == "right"), + flip = bar.hasClass("uk-offcanvas-bar-flip") ? -1:1, + dir = flip * (rtl ? -1 : 1), + + scrollbarwidth = window.innerWidth - $body.width(); + + scrollpos = {x: window.pageXOffset, y: window.pageYOffset}; + + element.addClass("uk-active"); + + $body.css({"width": window.innerWidth - scrollbarwidth, "height": window.innerHeight}).addClass("uk-offcanvas-page"); + $body.css((rtl ? "margin-right" : "margin-left"), (rtl ? -1 : 1) * (bar.outerWidth() * dir)).width(); // .width() - force redraw + + $html.css('margin-top', scrollpos.y * -1); + + bar.addClass("uk-offcanvas-bar-show"); + + this._initElement(element); + + bar.trigger('show.uk.offcanvas', [element, bar]); + + // Update ARIA + element.attr('aria-hidden', 'false'); + }, + + hide: function(force) { + + var $body = UI.$('body'), + panel = UI.$(".uk-offcanvas.uk-active"), + rtl = (UI.langdirection == "right"), + bar = panel.find(".uk-offcanvas-bar:first"), + finalize = function() { + $body.removeClass("uk-offcanvas-page").css({"width": "", "height": "", "margin-left": "", "margin-right": ""}); + panel.removeClass("uk-active"); + + bar.removeClass("uk-offcanvas-bar-show"); + $html.css('margin-top', ''); + window.scrollTo(scrollpos.x, scrollpos.y); + bar.trigger('hide.uk.offcanvas', [panel, bar]); + + // Update ARIA + panel.attr('aria-hidden', 'true'); + }; + + if (!panel.length) return; + + if (UI.support.transition && !force) { + + $body.one(UI.support.transition.end, function() { + finalize(); + }).css((rtl ? "margin-right" : "margin-left"), ""); + + setTimeout(function(){ + bar.removeClass("uk-offcanvas-bar-show"); + }, 0); + + } else { + finalize(); + } + }, + + _initElement: function(element) { + + if (element.data("OffcanvasInit")) return; + + element.on("click.uk.offcanvas swipeRight.uk.offcanvas swipeLeft.uk.offcanvas", function(e) { + + var target = UI.$(e.target); + + if (!e.type.match(/swipe/)) { + + if (!target.hasClass("uk-offcanvas-close")) { + if (target.hasClass("uk-offcanvas-bar")) return; + if (target.parents(".uk-offcanvas-bar:first").length) return; + } + } + + e.stopImmediatePropagation(); + Offcanvas.hide(); + }); + + element.on("click", "a[href*='#']", function(e){ + + var link = UI.$(this), + href = link.attr("href"); + + if (href == "#") { + return; + } + + UI.$doc.one('hide.uk.offcanvas', function() { + + var target; + + try { + target = UI.$(link[0].hash); + } catch (e){ + target = ''; + } + + if (!target.length) { + target = UI.$('[name="'+link[0].hash.replace('#','')+'"]'); + } + + if (target.length && UI.Utils.scrollToElement) { + UI.Utils.scrollToElement(target, UI.Utils.options(link.attr('data-uk-smooth-scroll') || '{}')); + } else { + window.location.href = href; + } + }); + + Offcanvas.hide(); + }); + + element.data("OffcanvasInit", true); + } + }; + + UI.component('offcanvasTrigger', { + + boot: function() { + + // init code + $html.on("click.offcanvas.uikit", "[data-uk-offcanvas]", function(e) { + + e.preventDefault(); + + var ele = UI.$(this); + + if (!ele.data("offcanvasTrigger")) { + var obj = UI.offcanvasTrigger(ele, UI.Utils.options(ele.attr("data-uk-offcanvas"))); + ele.trigger("click"); + } + }); + + $html.on('keydown.uk.offcanvas', function(e) { + + if (e.keyCode === 27) { // ESC + Offcanvas.hide(); + } + }); + }, + + init: function() { + + var $this = this; + + this.options = UI.$.extend({ + "target": $this.element.is("a") ? $this.element.attr("href") : false + }, this.options); + + this.on("click", function(e) { + e.preventDefault(); + Offcanvas.show($this.options.target); + }); + } + }); + + UI.offcanvas = Offcanvas; + +})(UIkit); + +(function(UI) { + + "use strict"; + + var Animations; + + UI.component('switcher', { + + defaults: { + connect : false, + toggle : ">*", + active : 0, + animation : false, + duration : 200, + swiping : true + }, + + animating: false, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-switcher]", context).each(function() { + var switcher = UI.$(this); + + if (!switcher.data("switcher")) { + var obj = UI.switcher(switcher, UI.Utils.options(switcher.attr("data-uk-switcher"))); + } + }); + }); + }, + + init: function() { + + var $this = this; + + this.on("click.uk.switcher", this.options.toggle, function(e) { + e.preventDefault(); + $this.show(this); + }); + + if (this.options.connect) { + + this.connect = UI.$(this.options.connect); + + this.connect.find(".uk-active").removeClass(".uk-active"); + + // delegate switch commands within container content + if (this.connect.length) { + + // Init ARIA for connect + this.connect.children().attr('aria-hidden', 'true'); + + this.connect.on("click", '[data-uk-switcher-item]', function(e) { + + e.preventDefault(); + + var item = UI.$(this).attr('data-uk-switcher-item'); + + if ($this.index == item) return; + + switch(item) { + case 'next': + case 'previous': + $this.show($this.index + (item=='next' ? 1:-1)); + break; + default: + $this.show(parseInt(item, 10)); + } + }); + + if (this.options.swiping) { + + this.connect.on('swipeRight swipeLeft', function(e) { + e.preventDefault(); + if(!window.getSelection().toString()) { + $this.show($this.index + (e.type == 'swipeLeft' ? 1 : -1)); + } + }); + } + } + + var toggles = this.find(this.options.toggle), + active = toggles.filter(".uk-active"); + + if (active.length) { + this.show(active, false); + } else { + + if (this.options.active===false) return; + + active = toggles.eq(this.options.active); + this.show(active.length ? active : toggles.eq(0), false); + } + + // Init ARIA for toggles + toggles.not(active).attr('aria-expanded', 'false'); + active.attr('aria-expanded', 'true'); + + this.on('changed.uk.dom', function() { + $this.connect = UI.$($this.options.connect); + }); + } + + }, + + show: function(tab, animate) { + + if (this.animating) { + return; + } + + if (isNaN(tab)) { + tab = UI.$(tab); + } else { + + var toggles = this.find(this.options.toggle); + + tab = tab < 0 ? toggles.length-1 : tab; + tab = toggles.eq(toggles[tab] ? tab : 0); + } + + var $this = this, + toggles = this.find(this.options.toggle), + active = UI.$(tab), + animation = Animations[this.options.animation] || function(current, next) { + + if (!$this.options.animation) { + return Animations.none.apply($this); + } + + var anim = $this.options.animation.split(','); + + if (anim.length == 1) { + anim[1] = anim[0]; + } + + anim[0] = anim[0].trim(); + anim[1] = anim[1].trim(); + + return coreAnimation.apply($this, [anim, current, next]); + }; + + if (animate===false || !UI.support.animation) { + animation = Animations.none; + } + + if (active.hasClass("uk-disabled")) return; + + // Update ARIA for Toggles + toggles.attr('aria-expanded', 'false'); + active.attr('aria-expanded', 'true'); + + toggles.filter(".uk-active").removeClass("uk-active"); + active.addClass("uk-active"); + + if (this.options.connect && this.connect.length) { + + this.index = this.find(this.options.toggle).index(active); + + if (this.index == -1 ) { + this.index = 0; + } + + this.connect.each(function() { + + var container = UI.$(this), + children = UI.$(container.children()), + current = UI.$(children.filter('.uk-active')), + next = UI.$(children.eq($this.index)); + + $this.animating = true; + + animation.apply($this, [current, next]).then(function(){ + + current.removeClass("uk-active"); + next.addClass("uk-active"); + + // Update ARIA for connect + current.attr('aria-hidden', 'true'); + next.attr('aria-hidden', 'false'); + + UI.Utils.checkDisplay(next, true); + + $this.animating = false; + + }); + }); + } + + this.trigger("show.uk.switcher", [active]); + } + }); + + Animations = { + + 'none': function() { + var d = UI.$.Deferred(); + d.resolve(); + return d.promise(); + }, + + 'fade': function(current, next) { + return coreAnimation.apply(this, ['uk-animation-fade', current, next]); + }, + + 'slide-bottom': function(current, next) { + return coreAnimation.apply(this, ['uk-animation-slide-bottom', current, next]); + }, + + 'slide-top': function(current, next) { + return coreAnimation.apply(this, ['uk-animation-slide-top', current, next]); + }, + + 'slide-vertical': function(current, next, dir) { + + var anim = ['uk-animation-slide-top', 'uk-animation-slide-bottom']; + + if (current && current.index() > next.index()) { + anim.reverse(); + } + + return coreAnimation.apply(this, [anim, current, next]); + }, + + 'slide-left': function(current, next) { + return coreAnimation.apply(this, ['uk-animation-slide-left', current, next]); + }, + + 'slide-right': function(current, next) { + return coreAnimation.apply(this, ['uk-animation-slide-right', current, next]); + }, + + 'slide-horizontal': function(current, next, dir) { + + var anim = ['uk-animation-slide-right', 'uk-animation-slide-left']; + + if (current && current.index() > next.index()) { + anim.reverse(); + } + + return coreAnimation.apply(this, [anim, current, next]); + }, + + 'scale': function(current, next) { + return coreAnimation.apply(this, ['uk-animation-scale-up', current, next]); + } + }; + + UI.switcher.animations = Animations; + + + // helpers + + function coreAnimation(cls, current, next) { + + var d = UI.$.Deferred(), clsIn = cls, clsOut = cls, release; + + if (next[0]===current[0]) { + d.resolve(); + return d.promise(); + } + + if (typeof(cls) == 'object') { + clsIn = cls[0]; + clsOut = cls[1] || cls[0]; + } + + UI.$body.css('overflow-x', 'hidden'); // fix scroll jumping in iOS + + release = function() { + + if (current) current.hide().removeClass('uk-active '+clsOut+' uk-animation-reverse'); + + next.addClass(clsIn).one(UI.support.animation.end, function() { + + next.removeClass(''+clsIn+'').css({opacity:'', display:''}); + + d.resolve(); + + UI.$body.css('overflow-x', ''); + + if (current) current.css({opacity:'', display:''}); + + }.bind(this)).show(); + }; + + next.css('animation-duration', this.options.duration+'ms'); + + if (current && current.length) { + + current.css('animation-duration', this.options.duration+'ms'); + + current.css('display', 'none').addClass(clsOut+' uk-animation-reverse').one(UI.support.animation.end, function() { + release(); + }.bind(this)).css('display', ''); + + } else { + next.addClass('uk-active'); + release(); + } + + return d.promise(); + } + +})(UIkit); + +(function(UI) { + + "use strict"; + + UI.component('tab', { + + defaults: { + 'target' : '>li:not(.uk-tab-responsive, .uk-disabled)', + 'connect' : false, + 'active' : 0, + 'animation' : false, + 'duration' : 200, + 'swiping' : true + }, + + boot: function() { + + // init code + UI.ready(function(context) { + + UI.$("[data-uk-tab]", context).each(function() { + + var tab = UI.$(this); + + if (!tab.data("tab")) { + var obj = UI.tab(tab, UI.Utils.options(tab.attr("data-uk-tab"))); + } + }); + }); + }, + + init: function() { + + var $this = this; + + this.current = false; + + this.on("click.uk.tab", this.options.target, function(e) { + + e.preventDefault(); + + if ($this.switcher && $this.switcher.animating) { + return; + } + + var current = $this.find($this.options.target).not(this); + + current.removeClass("uk-active").blur(); + + $this.trigger("change.uk.tab", [UI.$(this).addClass("uk-active"), $this.current]); + + $this.current = UI.$(this); + + // Update ARIA + if (!$this.options.connect) { + current.attr('aria-expanded', 'false'); + UI.$(this).attr('aria-expanded', 'true'); + } + }); + + if (this.options.connect) { + this.connect = UI.$(this.options.connect); + } + + // init responsive tab + this.responsivetab = UI.$('<li class="uk-tab-responsive uk-active"><a></a></li>').append('<div class="uk-dropdown uk-dropdown-small"><ul class="uk-nav uk-nav-dropdown"></ul><div>'); + + this.responsivetab.dropdown = this.responsivetab.find('.uk-dropdown'); + this.responsivetab.lst = this.responsivetab.dropdown.find('ul'); + this.responsivetab.caption = this.responsivetab.find('a:first'); + + if (this.element.hasClass("uk-tab-bottom")) this.responsivetab.dropdown.addClass("uk-dropdown-up"); + + // handle click + this.responsivetab.lst.on('click.uk.tab', 'a', function(e) { + + e.preventDefault(); + e.stopPropagation(); + + var link = UI.$(this); + + $this.element.children('li:not(.uk-tab-responsive)').eq(link.data('index')).trigger('click'); + }); + + this.on('show.uk.switcher change.uk.tab', function(e, tab) { + $this.responsivetab.caption.html(tab.text()); + }); + + this.element.append(this.responsivetab); + + // init UIkit components + if (this.options.connect) { + this.switcher = UI.switcher(this.element, { + 'toggle' : '>li:not(.uk-tab-responsive)', + 'connect' : this.options.connect, + 'active' : this.options.active, + 'animation' : this.options.animation, + 'duration' : this.options.duration, + 'swiping' : this.options.swiping + }); + } + + UI.dropdown(this.responsivetab, {"mode": "click", "preventflip": "y"}); + + // init + $this.trigger("change.uk.tab", [this.element.find(this.options.target).not('.uk-tab-responsive').filter('.uk-active')]); + + this.check(); + + UI.$win.on('resize orientationchange', UI.Utils.debounce(function(){ + if ($this.element.is(":visible")) $this.check(); + }, 100)); + + this.on('display.uk.check', function(){ + if ($this.element.is(":visible")) $this.check(); + }); + }, + + check: function() { + + var children = this.element.children('li:not(.uk-tab-responsive)').removeClass('uk-hidden'); + + if (!children.length) { + this.responsivetab.addClass('uk-hidden'); + return; + } + + var top = (children.eq(0).offset().top + Math.ceil(children.eq(0).height()/2)), + doresponsive = false, + item, link, clone; + + this.responsivetab.lst.empty(); + + children.each(function(){ + + if (UI.$(this).offset().top > top) { + doresponsive = true; + } + }); + + if (doresponsive) { + + for (var i = 0; i < children.length; i++) { + + item = UI.$(children.eq(i)); + link = item.find('a'); + + if (item.css('float') != 'none' && !item.attr('uk-dropdown')) { + + if (!item.hasClass('uk-disabled')) { + + clone = item[0].outerHTML.replace('<a ', '<a data-index="'+i+'" '); + + this.responsivetab.lst.append(clone); + } + + item.addClass('uk-hidden'); + } + } + } + + this.responsivetab[this.responsivetab.lst.children('li').length ? 'removeClass':'addClass']('uk-hidden'); + } + }); + +})(UIkit); + +(function(UI){ + + "use strict"; + + UI.component('cover', { + + defaults: { + automute : true + }, + + boot: function() { + + // auto init + UI.ready(function(context) { + + UI.$("[data-uk-cover]", context).each(function(){ + + var ele = UI.$(this); + + if(!ele.data("cover")) { + var plugin = UI.cover(ele, UI.Utils.options(ele.attr("data-uk-cover"))); + } + }); + }); + }, + + init: function() { + + this.parent = this.element.parent(); + + UI.$win.on('load resize orientationchange', UI.Utils.debounce(function(){ + this.check(); + }.bind(this), 100)); + + this.on("display.uk.check", function(e) { + if(this.element.is(":visible")) this.check(); + }.bind(this)); + + this.check(); + + if (this.element.is('iframe') && this.options.automute) { + + var src = this.element.attr('src'); + + this.element.attr('src', '').on('load', function(){ + + this.contentWindow.postMessage('{ "event": "command", "func": "mute", "method":"setVolume", "value":0}', '*'); + + }).attr('src', [src, (src.indexOf('?') > -1 ? '&':'?'), 'enablejsapi=1&api=1'].join('')); + } + }, + + check: function() { + + this.element.css({ + 'width' : '', + 'height' : '' + }); + + this.dimension = {w: this.element.width(), h: this.element.height()}; + + if (this.element.attr('width') && !isNaN(this.element.attr('width'))) { + this.dimension.w = this.element.attr('width'); + } + + if (this.element.attr('height') && !isNaN(this.element.attr('height'))) { + this.dimension.h = this.element.attr('height'); + } + + this.ratio = this.dimension.w / this.dimension.h; + + var w = this.parent.width(), h = this.parent.height(), width, height; + + // if element height < parent height (gap underneath) + if ((w / this.ratio) < h) { + + width = Math.ceil(h * this.ratio); + height = h; + + // element width < parent width (gap to right) + } else { + + width = w; + height = Math.ceil(w / this.ratio); + } + + this.element.css({ + 'width' : width, + 'height' : height + }); + } + }); + +})(UIkit);
--- a/hgext3rd/evolve/__init__.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/__init__.py Tue Jan 16 04:35:34 2018 +0100 @@ -72,15 +72,17 @@ # (needed on both client and server) obshashrange = yes - # avoid cache warming after transaction - # (recommended 'off' for developer repositories) - # (recommended 'yes' for server (default)) - obshashrange.warm-cache = no + # control cache warming at the end of transaction + # yes: warm all caches at the end of each transaction, + # off: warm no caches at the end of transaction, + # auto: warm cache at the end of server side transaction (default). + obshashrange.warm-cache = 'auto' -The initial cache warming is currently a bit slow. To make sure it is build you -can run the following commands in your repository:: +The initial cache warming might be a bit slow. To make sure it is build you +can run one of the following commands in your repository:: - $ hg debugobshashrange --rev 'head() + $ hg debugupdatecache # mercurial 4.3 and above + $ hg debugobshashrange --rev 'head() # mercurial 4.2 and below It is recommended to enable the blackbox extension. It gathers useful data about the experiment. It is shipped with Mercurial so no extra install is needed:: @@ -255,7 +257,6 @@ import sys import re import collections -import errno import struct try: @@ -311,6 +312,7 @@ compat, debugcmd, cmdrewrite, + evolvestate, exthelper, metadata, obscache, @@ -322,6 +324,7 @@ utility, ) +TROUBLES = compat.TROUBLES __version__ = metadata.__version__ testedwith = metadata.testedwith minimumhgversion = metadata.minimumhgversion @@ -423,6 +426,15 @@ if obsolete.isenabled(repo, 'exchange'): repo.ui.setconfig('server', 'bundle1', False) + class trdescrepo(repo.__class__): + + def transaction(self, desc, *args, **kwargs): + tr = super(trdescrepo, self).transaction(desc, *args, **kwargs) + tr.desc = desc + return tr + + repo.__class__ = trdescrepo + @eh.uisetup def _configurecmdoptions(ui): # Unregister evolve commands if the command capability is not specified. @@ -684,12 +696,14 @@ # This section take care of issue warning to the user when troubles appear -def _warnobsoletewc(ui, repo): +def _warnobsoletewc(ui, repo, prevnode=None, wasobs=None): rev = repo['.'] if not rev.obsolete(): return + if rev.node() == prevnode and wasobs: + return msg = _("working directory parent is obsolete! (%s)\n") shortnode = node.short(rev.node()) @@ -763,8 +777,12 @@ @eh.wrapcommand("pull") def wrapmayobsoletewc(origfn, ui, repo, *args, **opts): """Warn that the working directory parent is an obsolete changeset""" + ctx = repo['.'] + node = ctx.node() + isobs = ctx.obsolete() + def warnobsolete(): - _warnobsoletewc(ui, repo) + _warnobsoletewc(ui, repo, node, isobs) wlock = None try: wlock = repo.wlock() @@ -831,8 +849,8 @@ raise def summaryhook(ui, repo): - state = _evolvestateread(repo) - if state is not None: + state = evolvestate.evolvestate(repo) + if state: # i18n: column positioning for "hg summary" ui.status(_('evolve: (evolve --continue)\n')) @@ -1359,15 +1377,19 @@ fm.data(node=ctx.hex(), rev=ctx.rev(), desc=desc, phase=ctx.phasestr()) for unpar in unpars if showunstable else []: - fm.plain(' orphan: %s (orphan parent)\n' % unpar[:hashlen]) + fm.plain(' %s: %s (%s parent)\n' % (TROUBLES['ORPHAN'], + unpar[:hashlen], + TROUBLES['ORPHAN'])) for obspar in obspars if showunstable else []: - fm.plain(' unstable: %s (obsolete parent)\n' % obspar[:hashlen]) + fm.plain(' %s: %s (obsolete parent)\n' % (TROUBLES['ORPHAN'], + obspar[:hashlen])) for imprec in imprecs if showbumped else []: - fm.plain(' bumped: %s (immutable precursor)\n' % imprec[:hashlen]) + fm.plain(' %s: %s (immutable precursor)\n' % + (TROUBLES['PHASEDIVERGENT'], imprec[:hashlen])) if dsets and showdivergent: for dset in dsets: - fm.plain(' divergent: ') + fm.plain(' %s: ' % TROUBLES['CONTENTDIVERGENT']) first = True for n in dset['divergentnodes']: t = "%s (%s)" if first else " %s (%s)" @@ -1381,19 +1403,21 @@ _formatctx(fm, ctx) troubles = [] for unpar in unpars: - troubles.append({'troubletype': 'unstable', 'sourcenode': unpar, - 'sourcetype': 'unstableparent'}) + troubles.append({'troubletype': TROUBLES['ORPHAN'], + 'sourcenode': unpar, 'sourcetype': 'orphanparent'}) for obspar in obspars: - troubles.append({'troubletype': 'unstable', 'sourcenode': obspar, + troubles.append({'troubletype': TROUBLES['ORPHAN'], + 'sourcenode': obspar, 'sourcetype': 'obsoleteparent'}) for imprec in imprecs: - troubles.append({'troubletype': 'bumped', 'sourcenode': imprec, + troubles.append({'troubletype': TROUBLES['PHASEDIVERGENT'], + 'sourcenode': imprec, 'sourcetype': 'immutableprecursor'}) for dset in dsets: divnodes = [{'node': node.hex(n), 'phase': repo[n].phasestr(), } for n in dset['divergentnodes']] - troubles.append({'troubletype': 'divergent', + troubles.append({'troubletype': TROUBLES['CONTENTDIVERGENT'], 'commonprecursor': node.hex(dset['commonprecursor']), 'divergentnodes': divnodes}) fm.data(troubles=troubles) @@ -1493,8 +1517,8 @@ categories of troubles with the --unstable, --divergent or --bumped flags. """ + opts = _checkevolveopts(repo, opts) # Options - listopt = opts['list'] contopt = opts['continue'] anyopt = opts['any'] allopt = opts['all'] @@ -1503,33 +1527,11 @@ confirmopt = opts['confirm'] revopt = opts['rev'] - # Backward compatibility - if opts['unstable']: - msg = ("'evolve --unstable' is deprecated, " - "use 'evolve --orphan'") - repo.ui.deprecwarn(msg, '4.4') - - opts['orphan'] = opts['divergent'] - - if opts['divergent']: - msg = ("'evolve --divergent' is deprecated, " - "use 'evolve --content-divergent'") - repo.ui.deprecwarn(msg, '4.4') - - opts['content_divergent'] = opts['divergent'] - - if opts['bumped']: - msg = ("'evolve --bumped' is deprecated, " - "use 'evolve --phase-divergent'") - repo.ui.deprecwarn(msg, '4.4') - - opts['phase_divergent'] = opts['bumped'] - troublecategories = ['phase_divergent', 'content_divergent', 'orphan'] specifiedcategories = [t.replace('_', '') for t in troublecategories if opts[t]] - if listopt: + if opts['list']: compat.startpager(ui, 'evolve') listtroubles(ui, repo, specifiedcategories, **opts) return @@ -1578,34 +1580,38 @@ # Continuation handling if contopt: - if anyopt: - raise error.Abort('cannot specify both "--any" and "--continue"') - if allopt: - raise error.Abort('cannot specify both "--all" and "--continue"') - state = _evolvestateread(repo) - if state is None: + state = evolvestate.evolvestate(repo) + if not state: raise error.Abort('no evolve to continue') + state.load() orig = repo[state['current']] - # XXX This is a terrible terrible hack, please get rid of it. - lock = repo.wlock() - try: - repo.vfs.write('graftstate', orig.hex() + '\n') - try: - graftcmd = commands.table['graft'][0] - ret = graftcmd(ui, repo, old_obsolete=True, **{'continue': True}) - _evolvestatedelete(repo) - return ret - finally: - util.unlinkpath(repo.vfs.join('graftstate'), ignoremissing=True) - finally: - lock.release() + with repo.wlock(), repo.lock(): + ctx = orig + source = ctx.extra().get('source') + extra = {} + if source: + extra['source'] = source + extra['intermediate-source'] = ctx.hex() + else: + extra['source'] = ctx.hex() + user = ctx.user() + date = ctx.date() + message = ctx.description() + ui.status(_('evolving %d:%s "%s"\n') % (ctx.rev(), ctx, + message.split('\n', 1)[0])) + targetphase = max(ctx.phase(), phases.draft) + overrides = {('phases', 'new-commit'): targetphase} + + with repo.ui.configoverride(overrides, 'evolve-continue'): + node = repo.commit(text=message, user=user, + date=date, extra=extra) + + obsolete.createmarkers(repo, [(ctx, (repo[node],))]) + state.delete() + return + cmdutil.bailifchanged(repo) - if revopt and allopt: - raise error.Abort('cannot specify both "--rev" and "--all"') - if revopt and anyopt: - raise error.Abort('cannot specify both "--rev" and "--any"') - revs = _selectrevs(repo, allopt, revopt, anyopt, targetcat) if not revs: @@ -1624,6 +1630,46 @@ progresscb() _cleanup(ui, repo, startnode, showprogress) +def _checkevolveopts(repo, opts): + """ check the options passed to `hg evolve` and warn for deprecation warning + if any """ + + if opts['continue']: + if opts['any']: + raise error.Abort('cannot specify both "--any" and "--continue"') + if opts['all']: + raise error.Abort('cannot specify both "--all" and "--continue"') + + if opts['rev']: + if opts['any']: + raise error.Abort('cannot specify both "--rev" and "--any"') + if opts['all']: + raise error.Abort('cannot specify both "--rev" and "--all"') + + # Backward compatibility + if opts['unstable']: + msg = ("'evolve --unstable' is deprecated, " + "use 'evolve --orphan'") + repo.ui.deprecwarn(msg, '4.4') + + opts['orphan'] = opts['divergent'] + + if opts['divergent']: + msg = ("'evolve --divergent' is deprecated, " + "use 'evolve --content-divergent'") + repo.ui.deprecwarn(msg, '4.4') + + opts['content_divergent'] = opts['divergent'] + + if opts['bumped']: + msg = ("'evolve --bumped' is deprecated, " + "use 'evolve --phase-divergent'") + repo.ui.deprecwarn(msg, '4.4') + + opts['phase_divergent'] = opts['bumped'] + + return opts + def _possibledestination(repo, rev): """return all changesets that may be a new parent for REV""" tonode = repo.changelog.node @@ -1746,7 +1792,9 @@ try: relocate(repo, orig, target, pctx, keepbranch) except MergeFailure: - _evolvestatewrite(repo, {'current': orig.node()}) + ops = {'current': orig.node()} + state = evolvestate.evolvestate(repo, opts=ops) + state.save() repo.ui.write_err(_('evolve failed!\n')) repo.ui.write_err( _("fix conflict and run 'hg evolve --continue'" @@ -1784,7 +1832,8 @@ repo.ui.write(todo) repo.ui.write(('hg update %s;\n' % prec)) repo.ui.write(('hg revert --all --rev %s;\n' % bumped)) - repo.ui.write(('hg commit --msg "bumped update to %s"')) + repo.ui.write(('hg commit --msg "%s update to %s"\n' % + (TROUBLES['PHASEDIVERGENT'], bumped))) return 0 if progresscb: progresscb() @@ -1830,13 +1879,10 @@ if path in bumped: fctx = bumped[path] flags = fctx.flags() - mctx = context.memfilectx(repo, fctx.path(), fctx.data(), - islink='l' in flags, - isexec='x' in flags, - copied=copied.get(path)) + mctx = compat.memfilectx(repo, ctx, fctx, flags, copied, path) return mctx return None - text = 'bumped update to %s:\n\n' % prec + text = '%s update to %s:\n\n' % (TROUBLES['PHASEDIVERGENT'], prec) text += bumped.description() new = context.memctx(repo, @@ -1869,7 +1915,7 @@ base, others = divergentdata(divergent) if len(others) > 1: othersstr = "[%s]" % (','.join([str(i) for i in others])) - msg = _("skipping %d:divergent with a changeset that got split" + msg = _("skipping %d:%s with a changeset that got split" " into multiple ones:\n" "|[%s]\n" "| This is not handled by automatic evolution yet\n" @@ -1879,13 +1925,13 @@ "| - hg prune\n" "| \n" "| You should contact your local evolution Guru for help.\n" - ) % (divergent, othersstr) + ) % (divergent, TROUBLES['CONTENTDIVERGENT'], othersstr) ui.write_err(msg) return 2 other = others[0] if len(other.parents()) > 1: - msg = _("skipping %s: divergent changeset can't be " - "a merge (yet)\n") % divergent + msg = _("skipping %s: %s changeset can't be " + "a merge (yet)\n") % (divergent, TROUBLES['CONTENTDIVERGENT']) ui.write_err(msg) hint = _("You have to fallback to solving this by hand...\n" "| This probably means redoing the merge and using \n" @@ -1930,7 +1976,7 @@ if divergent not in repo[None].parents(): repo.ui.status(_('updating to "local" conflict\n')) hg.update(repo, divergent.rev()) - repo.ui.note(_('merging divergent changeset\n')) + repo.ui.note(_('merging %s changeset\n') % TROUBLES['CONTENTDIVERGENT']) if progresscb: progresscb() stats = merge.update(repo, @@ -2036,6 +2082,8 @@ # we do not filter in the 1 case to allow prev to t0 if currenttopic and topic and _gettopicidx(p1) != 1: + parents = [repo[_singlesuccessor(repo, ctx)] if ctx.mutable() else ctx + for ctx in parents] parents = [ctx for ctx in parents if ctx.topic() == currenttopic] # issue message for the various case @@ -2435,70 +2483,6 @@ util.unlinkpath(repo.vfs.join('evolvestate'), ignoremissing=True) return ret -def _evolvestatewrite(repo, state): - # [version] - # [type][length][content] - # - # `version` is a 4 bytes integer (handled at higher level) - # `type` is a single character, `length` is a 4 byte integer, and - # `content` is an arbitrary byte sequence of length `length`. - f = repo.vfs('evolvestate', 'w') - try: - f.write(_pack('>I', evolvestateversion)) - current = state['current'] - key = 'C' # as in 'current' - format = '>sI%is' % len(current) - f.write(_pack(format, key, len(current), current)) - finally: - f.close() - -def _evolvestateread(repo): - try: - f = repo.vfs('evolvestate') - except IOError as err: - if err.errno != errno.ENOENT: - raise - return None - try: - versionblob = f.read(4) - if len(versionblob) < 4: - repo.ui.debug('ignoring corrupted evolvestate (file contains %i bits)' - % len(versionblob)) - return None - version = _unpack('>I', versionblob)[0] - if version != evolvestateversion: - msg = _('unknown evolvestate version %i') % version - raise error.Abort(msg, hint=_('upgrade your evolve')) - records = [] - data = f.read() - off = 0 - end = len(data) - while off < end: - rtype = data[off] - off += 1 - length = _unpack('>I', data[off:(off + 4)])[0] - off += 4 - record = data[off:(off + length)] - off += length - if rtype == 't': - rtype, record = record[0], record[1:] - records.append((rtype, record)) - state = {} - for rtype, rdata in records: - if rtype == 'C': - state['current'] = rdata - elif rtype.lower(): - repo.ui.debug('ignore evolve state record type %s' % rtype) - else: - raise error.Abort(_('unknown evolvestate field type %r') - % rtype, hint=_('upgrade your evolve')) - return state - finally: - f.close() - -def _evolvestatedelete(repo): - util.unlinkpath(repo.vfs.join('evolvestate'), ignoremissing=True) - def _evolvemerge(repo, orig, dest, pctx, keepbranch): """Used by the evolve function to merge dest on top of pctx. return the same tuple as merge.graft""" @@ -2521,4 +2505,4 @@ with repo.vfs.open('topic', 'w') as f: f.write(orig.topic()) - return merge.graft(repo, orig, pctx, ['local', 'graft'], True) + return merge.graft(repo, orig, pctx, ['destination', 'evolving'], True)
--- a/hgext3rd/evolve/cmdrewrite.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/cmdrewrite.py Tue Jan 16 04:35:34 2018 +0100 @@ -108,7 +108,7 @@ If you don't specify -m, the parent's message will be reused. - If --extra is specified, the behavior of `hg amend` is reversed: Changes + If --extract is specified, the behavior of `hg amend` is reversed: Changes to selected files in the checked out revision appear again as uncommitted changed in the working directory. @@ -179,10 +179,7 @@ return None fctx = contentctx[path] flags = fctx.flags() - mctx = context.memfilectx(repo, fctx.path(), fctx.data(), - islink='l' in flags, - isexec='x' in flags, - copied=copied.get(path)) + mctx = compat.memfilectx(repo, memctx, fctx, flags, copied, path) return mctx if message is None: @@ -305,6 +302,7 @@ [('a', 'all', None, _('uncommit all changes when no arguments given')), ('i', 'interactive', False, _('interactive mode to uncommit (EXPERIMENTAL)')), ('r', 'rev', '', _('revert commit content to REV instead')), + ('', 'revert', False, _('discard working directory changes after uncommit')), ('n', 'note', '', _('store a note on uncommit')), ] + commands.walkopts + commitopts + commitopts2 + commitopts3, _('[OPTION]... [NAME]')) @@ -391,9 +389,12 @@ obsolete.createmarkers(repo, [(old, (repo[newid],))], metadata=metadata) phases.retractboundary(repo, tr, oldphase, [newid]) - with repo.dirstate.parentchange(): - repo.dirstate.setparents(newid, node.nullid) - _uncommitdirstate(repo, old, match, interactive) + if opts.get('revert'): + hg.updaterepo(repo, newid, True) + else: + with repo.dirstate.parentchange(): + repo.dirstate.setparents(newid, node.nullid) + _uncommitdirstate(repo, old, match, interactive) updatebookmarks(newid) if not repo[newid].files(): ui.warn(_("new changeset is empty\n"))
--- a/hgext3rd/evolve/compat.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/compat.py Tue Jan 16 04:35:34 2018 +0100 @@ -15,6 +15,13 @@ util, ) +# hg < 4.2 compat +try: + from mercurial import vfs as vfsmod + vfsmod.vfs +except ImportError: + from mercurial import scmutil as vfsmod + try: from mercurial import obsutil obsutil.closestpredecessors @@ -195,3 +202,27 @@ copies.duplicatecopies(repo, rev, fromrev, skiprev=skiprev) else: copies.duplicatecopies(repo, wctx, rev, fromrev, skiprev=skiprev) + +def memfilectx(repo, ctx, fctx, flags, copied, path): + # XXX Would it be better at the module level? + varnames = context.memfilectx.__init__.__code__.co_varnames + ctxmandatory = varnames[2] == "changectx" + + if ctxmandatory: + mctx = context.memfilectx(repo, ctx, fctx.path(), fctx.data(), + islink='l' in flags, + isexec='x' in flags, + copied=copied.get(path)) + else: + mctx = context.memfilectx(repo, fctx.path(), fctx.data(), + islink='l' in flags, + isexec='x' in flags, + copied=copied.get(path)) + return mctx + +def getcachevfs(repo): + cachevfs = getattr(repo, 'cachevfs', None) + if cachevfs is None: + cachevfs = vfsmod.vfs(repo.vfs.join('cache')) + cachevfs.createmode = repo.store.createmode + return cachevfs
--- a/hgext3rd/evolve/depthcache.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/depthcache.py Tue Jan 16 04:35:34 2018 +0100 @@ -1,3 +1,12 @@ +# Code dedicated to the caching of changeset depth +# +# These stable ranges are use for obsolescence markers discovery +# +# Copyright 2017 Pierre-Yves David <pierre-yves.david@ens-lyon.org> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + from __future__ import absolute_import import array @@ -5,19 +14,22 @@ from mercurial import ( localrepo, - node as nodemod, util, scmutil, ) from . import ( + compat, error, exthelper, genericcaches, + utility, ) from mercurial.i18n import _ +filterparents = utility.filterparents + eh = exthelper.exthelper() def simpledepth(repo, rev): @@ -36,7 +48,7 @@ """ revs = scmutil.revrange(repo, opts['rev']) method = opts['method'] - if method == 'cached': + if method in ('cached', 'compare'): cache = repo.depthcache cache.save(repo) for r in revs: @@ -51,6 +63,7 @@ if simple != cached: raise error.Abort('depth differ for revision %s: %d != %d' % (ctx, simple, cached)) + depth = simple else: raise error.Abort('unknown method "%s"' % method) ui.write('%s %d\n' % (ctx, depth)) @@ -68,20 +81,16 @@ @localrepo.unfilteredmethod def destroyed(self): - if 'obsstore' in vars(self): + if 'depthcache' in vars(self): self.depthcache.clear() super(depthcacherepo, self).destroyed() if util.safehasattr(repo, 'updatecaches'): @localrepo.unfilteredmethod def updatecaches(self, tr=None): - if (repo.ui.configbool('experimental', 'obshashrange', - False) - and repo.ui.configbool('experimental', - 'obshashrange.warm-cache', - True)): - self.depthcache.update(repo) - self.depthcache.save(repo) + if utility.shouldwarmcache(self, tr): + self.depthcache.update(self) + self.depthcache.save(self) super(depthcacherepo, self).updatecaches(tr) else: @@ -94,19 +103,11 @@ if repo is None: return repo = repo.unfiltered() - # As pointed in 'obscache.update', we could have the changelog - # and the obsstore in charge of updating the cache when new - # items goes it. The tranaction logic would then only be - # involved for the 'pending' and final writing on disk. - self.obsstore.obscache.update(repo) - self.obsstore.obscache.save(repo) + repo.depthcache.update(repo) + repo.depthcache.save(repo) - if (repo.ui.configbool('experimental', 'obshashrange', - False) - and repo.ui.configbool('experimental', - 'obshashrange.warm-cache', - True)): - tr.addpostclose('warmcache-depthcache', _warmcache) + if utility.shouldwarmcache(self, tr): + tr.addpostclose('warmcache-00depthcache', _warmcache) return tr repo.__class__ = depthcacherepo @@ -144,14 +145,15 @@ def _depth(self, changelog, rev): cl = changelog - p1, p2 = cl.parentrevs(rev) - if p1 == nodemod.nullrev: + ps = filterparents(cl.parentrevs(rev)) + if not ps: # root case return 1 - elif p2 == nodemod.nullrev: + elif len(ps) == 1: # linear commit case - return self.get(p1) + 1 + return self.get(ps[0]) + 1 # merge case, must find the amount of exclusive content + p1, p2 = ps depth_p1 = self.get(p1) depth_p2 = self.get(p2) # computing depth of a merge @@ -196,10 +198,8 @@ """load data from disk""" assert repo.filtername is None - if util.safehasattr(repo, 'cachevfs'): - data = repo.cachevfs.tryread(self._filepath) - else: - data = repo.vfs.tryread('cache/' + self._filepath) + cachevfs = compat.getcachevfs(repo) + data = cachevfs.tryread(self._filepath) self._data = array.array('l') if not data: self._cachekey = self.emptykey @@ -218,10 +218,8 @@ if self._cachekey is None or self._cachekey == self._ondiskkey: return - if util.safehasattr(repo, 'cachevfs'): - cachefile = repo.cachevfs(self._filepath, 'w', atomictemp=True) - else: - cachefile = repo.vfs('cache/' + self._filepath, 'w', atomictemp=True) + cachevfs = compat.getcachevfs(repo) + cachefile = cachevfs(self._filepath, 'w', atomictemp=True) headerdata = self._serializecachekey() cachefile.write(headerdata) cachefile.write(self._data.tostring())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/evolvestate.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,74 @@ +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +""" +This file contains class to wrap the state for hg evolve command and other +related logic. + +All the data related to the command state is stored as dictionary in the object. +The class has methods using which the data can be stored to disk in +.hg/evolvestate file. + +We store the data on disk in cbor, for which we use cbor library to serialize +and deserialize data. +""" + +from __future__ import absolute_import + +from .thirdparty import cbor + +from mercurial import ( + util, +) + +class evolvestate(): + """a wrapper class to store the state of `hg evolve` command + + All the data for the state is stored in the form of key-value pairs in a + dictionary. + + The class object can write all the data to .hg/evolvestate file and also can + populate the object data reading that file + """ + + def __init__(self, repo, path='evolvestate', opts={}): + self._repo = repo + self.path = path + self.opts = opts + + def __nonzero__(self): + return self.exists() + + def __getitem__(self, key): + return self.opts[key] + + def load(self): + """load the existing evolvestate file into the class object""" + op = self._read() + self.opts.update(op) + + def addopts(self, opts): + """add more key-value pairs to the data stored by the object""" + self.opts.update(opts) + + def save(self): + """write all the evolvestate data stored in .hg/evolvestate file + + we use third-party library cbor to serialize data to write in the file. + """ + with self._repo.vfs(self.path, 'wb', atomictemp=True) as fp: + cbor.dump(self.opts, fp) + + def _read(self): + """reads the evolvestate file and returns a dictionary which contain + data in the same format as it was before storing""" + with self._repo.vfs(self.path, 'rb') as fp: + return cbor.load(fp) + + def delete(self): + """drop the evolvestate file if exists""" + util.unlinkpath(self._repo.vfs.join(self.path), ignoremissing=True) + + def exists(self): + """check whether the evolvestate file exists or not""" + return self._repo.vfs.exists(self.path)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/firstmergecache.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,163 @@ +# Code dedicated to the cache of 'max(merge()) and ::X' +# +# These stable ranges are use for obsolescence markers discovery +# +# Copyright 2017 Pierre-Yves David <pierre-yves.david@ens-lyon.org> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +from __future__ import absolute_import + +import array +import weakref + +from mercurial import ( + localrepo, + node as nodemod, + util, +) + +from . import ( + compat, + error, + exthelper, + genericcaches, + utility, +) + +filterparents = utility.filterparents + +eh = exthelper.exthelper() + +@eh.reposetup +def setupcache(ui, repo): + + class firstmergecacherepo(repo.__class__): + + @localrepo.unfilteredpropertycache + def firstmergecache(self): + cache = firstmergecache() + cache.update(self) + return cache + + @localrepo.unfilteredmethod + def destroyed(self): + if 'firstmergecach' in vars(self): + self.firstmergecache.clear() + super(firstmergecacherepo, self).destroyed() + + if util.safehasattr(repo, 'updatecaches'): + @localrepo.unfilteredmethod + def updatecaches(self, tr=None): + if utility.shouldwarmcache(self, tr): + self.firstmergecache.update(self) + self.firstmergecache.save(self) + super(firstmergecacherepo, self).updatecaches(tr) + + else: + def transaction(self, *args, **kwargs): + tr = super(firstmergecacherepo, self).transaction(*args, **kwargs) + reporef = weakref.ref(self) + + def _warmcache(tr): + repo = reporef() + if repo is None: + return + repo = repo.unfiltered() + repo.firstmergecache.update(repo) + repo.firstmergecache.save(repo) + + if utility.shouldwarmcache(self, tr): + tr.addpostclose('warmcache-01-firstparentcache', _warmcache) + return tr + + repo.__class__ = firstmergecacherepo + +class firstmergecache(genericcaches.changelogsourcebase): + + _filepath = 'evoext-firstmerge-00' + _cachename = 'evo-ext-firstmerge' + + def __init__(self): + super(firstmergecache, self).__init__() + self._data = array.array('l') + + def get(self, rev): + if len(self._data) <= rev: + raise error.ProgrammingError('firstmergecache must be warmed before use') + return self._data[rev] + + def _updatefrom(self, repo, data): + """compute the rev of one revision, assert previous revision has an hot cache + """ + cl = repo.unfiltered().changelog + total = len(data) + + def progress(pos, rev): + repo.ui.progress('updating firstmerge cache', + pos, 'rev %s' % rev, unit='revision', total=total) + progress(0, '') + for idx, rev in enumerate(data, 1): + assert rev == len(self._data), (rev, len(self._data)) + self._data.append(self._firstmerge(cl, rev)) + if not (idx % 10000): # progress as a too high performance impact + progress(idx, rev) + progress(None, '') + + def _firstmerge(self, changelog, rev): + cl = changelog + ps = filterparents(cl.parentrevs(rev)) + if not ps: + return nodemod.nullrev + elif len(ps) == 1: + # linear commit case + return self.get(ps[0]) + else: + return rev + + # cache internal logic + + def clear(self, reset=False): + """invalidate the cache content + + if 'reset' is passed, we detected a strip and the cache will have to be + recomputed. + + Subclasses MUST overide this method to actually affect the cache data. + """ + super(firstmergecache, self).clear() + self._data = array.array('l') + + # crude version of a cache, to show the kind of information we have to store + + def load(self, repo): + """load data from disk""" + assert repo.filtername is None + + cachevfs = compat.getcachevfs(repo) + data = cachevfs.tryread(self._filepath) + self._data = array.array('l') + if not data: + self._cachekey = self.emptykey + else: + headerdata = data[:self._cachekeysize] + self._cachekey = self._deserializecachekey(headerdata) + self._data.fromstring(data[self._cachekeysize:]) + self._ondiskkey = self._cachekey + + def save(self, repo): + """save the data to disk + + Format is pretty simple, we serialise the cache key and then drop the + bytearray. + """ + if self._cachekey is None or self._cachekey == self._ondiskkey: + return + + cachevfs = compat.getcachevfs(repo) + cachefile = cachevfs(self._filepath, 'w', atomictemp=True) + headerdata = self._serializecachekey() + cachefile.write(headerdata) + cachefile.write(self._data.tostring()) + cachefile.close()
--- a/hgext3rd/evolve/metadata.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/metadata.py Tue Jan 16 04:35:34 2018 +0100 @@ -5,7 +5,7 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. -__version__ = '7.1.1.dev' +__version__ = '7.2.0' testedwith = '4.1.3 4.2.3 4.3.2 4.4.2' minimumhgversion = '4.1' buglink = 'https://bz.mercurial-scm.org/'
--- a/hgext3rd/evolve/obscache.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/obscache.py Tue Jan 16 04:35:34 2018 +0100 @@ -27,6 +27,7 @@ from mercurial.i18n import _ from . import ( + compat, exthelper, ) @@ -42,12 +43,6 @@ else: timer = time.time -# hg < 4.2 compat -try: - from mercurial import vfs as vfsmod - vfsmod.vfs -except ImportError: - from mercurial import scmutil as vfsmod obsstorefilecache = localrepo.localrepository.obsstore @@ -103,7 +98,7 @@ return obsstore -if obsolete._fm0readmarkers.__code__.co_argcount > 1: +if obsolete._fm0readmarkers.__code__.co_argcount > 2: # hg-4.3+ has the "offset" parameter, and _fm?readmarkers also have an # extra "stop" parameter # Note that _readmarkers is wrapped by @util.nogc, so its co_argcount is @@ -326,13 +321,6 @@ return reset, revs, markers, (obssize, obskey) -def getcachevfs(repo): - cachevfs = getattr(repo, 'cachevfs', None) - if cachevfs is None: - cachevfs = vfsmod.vfs(repo.vfs.join('cache')) - cachevfs.createmode = repo.store.createmode - return cachevfs - class obscache(dualsourcecache): """cache the "does a rev" is the precursors of some obsmarkers data @@ -375,7 +363,7 @@ def __init__(self, repo): super(obscache, self).__init__() self._ondiskkey = None - self._vfs = getcachevfs(repo) + self._vfs = compat.getcachevfs(repo) @util.propertycache def get(self):
--- a/hgext3rd/evolve/obsdiscovery.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/obsdiscovery.py Tue Jan 16 04:35:34 2018 +0100 @@ -52,6 +52,7 @@ obscache, utility, stablerange, + stablerangecache, ) # prior to hg-4.2 there are not util.timer @@ -69,7 +70,7 @@ _calcsize = struct.calcsize eh = exthelper.exthelper() -eh.merge(stablerange.eh) +eh.merge(stablerangecache.eh) obsexcmsg = utility.obsexcmsg # Config @@ -244,7 +245,7 @@ # question are asked with node n = repo.changelog.node noderanges = [(n(entry[0]), entry[1]) for entry in allentries] - replies = remote.evoext_obshashrange_v0(noderanges) + replies = remote.evoext_obshashrange_v1(noderanges) result = [] for idx, entry in enumerate(allentries): result.append((entry, replies[idx])) @@ -352,17 +353,19 @@ _queryobshash = "SELECT obshash FROM obshashrange WHERE (rev = ? AND idx = ?);" _reset = "DELETE FROM obshashrange;" +_delete = "DELETE FROM obshashrange WHERE (rev = ? AND idx = ?);" class _obshashcache(obscache.dualsourcecache): _schemaversion = 2 _cachename = 'evo-ext-obshashrange' # used for error message + _filename = 'cache/evoext_obshashrange_v2.sqlite' def __init__(self, repo): super(_obshashcache, self).__init__() self._vfs = repo.vfs - self._path = repo.vfs.join('cache/evoext_obshashrange_v1.sqlite') + self._path = repo.vfs.join(self._filename) self._new = set() self._valid = True self._repo = weakref.ref(repo.unfiltered()) @@ -433,12 +436,18 @@ affected.add(r) if affected: - repo.ui.log('evoext-cache', 'obshashcache reset - ' - 'new markers affect cached ranges\n') + repo.ui.log('evoext-cache', 'obshashcache clean - ' + 'new markers affect %d changeset and cached ranges\n' + % len(affected)) # XXX the current reset is too strong we could just drop the affected range con = self._con if con is not None: con.execute(_reset) + + ranges = repo.stablerange.contains(repo, affected) + + con.executemany(_delete, ranges) + # rewarm key revisions # # (The current invalidation is too wide, but rewarming every single @@ -446,15 +455,23 @@ newrevs = [] stop = self._cachekey[0] # tiprev for h in repo.filtered('immutable').changelog.headrevs(): - if h <= stop: + if h <= stop and h in affected: newrevs.append(h) newrevs.extend(revs) revs = newrevs repo.depthcache.update(repo) + total = len(revs) + + def progress(pos, rev): + repo.ui.progress('updating obshashrange cache', + pos, 'rev %s' % rev, unit='revision', total=total) # warm the cache for the new revs - for r in revs: + progress(0, '') + for idx, r in enumerate(revs): _obshashrange(repo, (r, 0)) + progress(idx, r) + progress(None, '') del self._updating @@ -578,30 +595,30 @@ self.obsstore.rangeobshashcache.clear() super(obshashrepo, self).destroyed() - def transaction(self, *args, **kwargs): - tr = super(obshashrepo, self).transaction(*args, **kwargs) - reporef = weakref.ref(self) + if util.safehasattr(repo, 'updatecaches'): + @localrepo.unfilteredmethod + def updatecaches(self, tr=None): + if utility.shouldwarmcache(self, tr): + self.obsstore.rangeobshashcache.update(self) + self.obsstore.rangeobshashcache.save(self) + super(obshashrepo, self).updatecaches(tr) - def _warmcache(tr): - repo = reporef() - if repo is None: - return - hasobshashrange = _useobshashrange(repo) - hascachewarm = repo.ui.configbool('experimental', - 'obshashrange.warm-cache', - True) - if not (hasobshashrange and hascachewarm): - return - repo = repo.unfiltered() - # As pointed in 'obscache.update', we could have the changelog - # and the obsstore in charge of updating the cache when new - # items goes it. The tranaction logic would then only be - # involved for the 'pending' and final writing on disk. - self.obsstore.rangeobshashcache.update(repo) - self.obsstore.rangeobshashcache.save(repo) + else: + def transaction(self, *args, **kwargs): + tr = super(obshashrepo, self).transaction(*args, **kwargs) + reporef = weakref.ref(self) - tr.addpostclose('warmcache-20-obscacherange', _warmcache) - return tr + def _warmcache(tr): + repo = reporef() + if repo is None: + return + repo = repo.unfiltered() + repo.obsstore.rangeobshashcache.update(repo) + repo.obsstore.rangeobshashcache.save(repo) + + if utility.shouldwarmcache(self, tr): + tr.addpostclose('warmcache-20obshashrange', _warmcache) + return tr repo.__class__ = obshashrepo @@ -629,7 +646,7 @@ repo.obsstore.rangeobshashcache.save(repo) return result -@eh.addattr(localrepo.localpeer, 'evoext_obshashrange_v0') +@eh.addattr(localrepo.localpeer, 'evoext_obshashrange_v1') def local_obshashrange_v0(peer, ranges): return _obshashrange_v0(peer._repo, ranges) @@ -648,17 +665,17 @@ index = _unpack(_indexformat, data[-_indexsize:])[0] return (headnode, index) -@eh.addattr(wireproto.wirepeer, 'evoext_obshashrange_v0') +@eh.addattr(wireproto.wirepeer, 'evoext_obshashrange_v1') def peer_obshashrange_v0(self, ranges): binranges = [_encrange(r) for r in ranges] encranges = wireproto.encodelist(binranges) - d = self._call("evoext_obshashrange_v0", ranges=encranges) + d = self._call("evoext_obshashrange_v1", ranges=encranges) try: return wireproto.decodelist(d) except ValueError: self._abort(error.ResponseError(_("unexpected response:"), d)) -def srv_obshashrange_v0(repo, proto, ranges): +def srv_obshashrange_v1(repo, proto, ranges): ranges = wireproto.decodelist(ranges) ranges = [_decrange(r) for r in ranges] hashes = _obshashrange_v0(repo, ranges) @@ -674,7 +691,7 @@ def _canobshashrange(local, remote): return (_useobshashrange(local) - and remote.capable('_evoext_obshashrange_v0')) + and remote.capable('_evoext_obshashrange_v1')) def _obshashrange_capabilities(orig, repo, proto): """wrapper to advertise new capability""" @@ -682,16 +699,16 @@ enabled = _useobshashrange(repo) if obsolete.isenabled(repo, obsolete.exchangeopt) and enabled: caps = caps.split() - caps.append('_evoext_obshashrange_v0') + caps.append('_evoext_obshashrange_v1') caps.sort() caps = ' '.join(caps) return caps @eh.extsetup def obshashrange_extsetup(ui): - hgweb_mod.perms['evoext_obshashrange_v0'] = 'pull' + hgweb_mod.perms['evoext_obshashrange_v1'] = 'pull' - wireproto.commands['evoext_obshashrange_v0'] = (srv_obshashrange_v0, 'ranges') + wireproto.commands['evoext_obshashrange_v1'] = (srv_obshashrange_v1, 'ranges') ### extensions.wrapfunction(wireproto, 'capabilities', _obshashrange_capabilities) # wrap command content
--- a/hgext3rd/evolve/obshistory.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/obshistory.py Tue Jan 16 04:35:34 2018 +0100 @@ -163,33 +163,15 @@ return True, succ -def _indent(content, indent=4): - extra = ' ' * indent - return "".join(extra + line for line in content.splitlines(True)) - -def getmarkercontentpatch(repo, node, succ): - # Todo get the ops from the cmd - diffopts = patch.diffallopts(repo.ui, {}) - matchfn = scmutil.matchall(repo) - - repo.ui.pushbuffer() - cmdutil.diffordiffstat(repo.ui, repo, diffopts, node, succ, - match=matchfn, stat=False) - buffer = repo.ui.popbuffer() - - return _indent(buffer) - -def getmarkerdescriptionpatch(repo, base, succ): - basectx = repo[base] - succctx = repo[succ] +def getmarkerdescriptionpatch(repo, basedesc, succdesc): # description are stored without final new line, # add one to avoid ugly diff - basedesc = basectx.description() + '\n' - succdesc = succctx.description() + '\n' + basedesc += '\n' + succdesc += '\n' # fake file name - basename = "%s-changeset-description" % basectx - succname = "%s-changeset-description" % succctx + basename = "changeset-description" + succname = "changeset-description" d = mdiff.unidiff(basedesc, '', succdesc, '', basename, succname) # mercurial 4.1 and before return the patch directly @@ -201,7 +183,8 @@ # Copied from patch.diff text = ''.join(sum((list(hlines) for hrange, hlines in hunks), [])) patch = "\n".join(uheaders + [text]) - return _indent(patch) + + return patch class missingchangectx(object): ''' a minimal object mimicking changectx for change contexts @@ -511,22 +494,48 @@ if _patchavailable[0] is True: succ = _patchavailable[1] + basectx = repo[node] + succctx = repo[succ] # Description patch - descriptionpatch = getmarkerdescriptionpatch(repo, node, succ) + descriptionpatch = getmarkerdescriptionpatch(repo, + basectx.description(), + succctx.description()) + if descriptionpatch: + # add the diffheader + diffheader = "diff -r %s -r %s changeset-description\n" % \ + (basectx, succctx) + descriptionpatch = diffheader + descriptionpatch + + def tolist(text): + return [text] + fm.plain("\n") - fm.plain(descriptionpatch) + + for chunk, label in patch.difflabel(tolist, descriptionpatch): + chunk = chunk.strip('\t') + if chunk and chunk != '\n': + fm.plain(' ') + fm.write('desc-diff', '%s', chunk, label=label) # Content patch - contentpatch = getmarkercontentpatch(repo, node, succ) - if contentpatch: - fm.plain("\n") - fm.plain(contentpatch) + diffopts = patch.diffallopts(repo.ui, {}) + matchfn = scmutil.matchall(repo) + firstline = True + for chunk, label in patch.diffui(repo, node, succ, matchfn, + changes=None, opts=diffopts, + prefix='', relroot=''): + if firstline: + fm.plain('\n') + firstline = False + if chunk and chunk != '\n': + fm.plain(' ') + fm.write('patch', '%s', chunk, label=label) else: - patch = " (No patch available, %s)" % _patchavailable[1] + nopatch = " (No patch available, %s)" % _patchavailable[1] fm.plain("\n") # TODO: should be in json too - fm.plain(patch) + fm.plain(nopatch) fm.plain("\n")
--- a/hgext3rd/evolve/rewriteutil.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/rewriteutil.py Tue Jan 16 04:35:34 2018 +0100 @@ -201,10 +201,7 @@ if path in headmf: fctx = head[path] flags = fctx.flags() - mctx = context.memfilectx(repo, fctx.path(), fctx.data(), - islink='l' in flags, - isexec='x' in flags, - copied=copied.get(path)) + mctx = compat.memfilectx(repo, ctx, fctx, flags, copied, path) return mctx return None
--- a/hgext3rd/evolve/stablerange.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/stablerange.py Tue Jan 16 04:35:34 2018 +0100 @@ -8,16 +8,14 @@ # GNU General Public License version 2 or any later version. import abc +import functools import heapq import math import os -import sqlite3 import time -import weakref from mercurial import ( error, - localrepo, node as nodemod, pycompat, scmutil, @@ -27,12 +25,17 @@ from mercurial.i18n import _ from . import ( + exthelper, + firstmergecache, stablesort, - exthelper, + utility, ) +filterparents = utility.filterparents + eh = exthelper.exthelper() eh.merge(stablesort.eh) +eh.merge(firstmergecache.eh) # prior to hg-4.2 there are not util.timer if util.safehasattr(util, 'timer'): @@ -74,7 +77,8 @@ return ranges _stablerangemethodmap = { - 'branchpoint': lambda repo: repo.stablerange, + 'branchpoint': lambda repo: stablerange(), + 'default': lambda repo: repo.stablerange, 'basic-branchpoint': lambda repo: stablerangebasic(), 'basic-mergepoint': lambda repo: stablerangedummy_mergepoint(), 'mergepoint': lambda repo: stablerange_mergepoint(), @@ -298,6 +302,11 @@ __metaclass__ = abc.ABCMeta + def __init__(self): + # cache the standard stable subranges or a range + self._subrangescache = {} + super(stablerangecached, self).__init__() + def depthrev(self, repo, rev): return repo.depthcache.get(rev) @@ -306,16 +315,37 @@ headrev, index = rangeid[0], rangeid[1] return self.depthrev(repo, headrev) - index -class stablerange_mergepoint(stablerangecached, stablerangebasic): + def subranges(self, repo, rangeid): + assert 0 <= rangeid[1] <= rangeid[0], rangeid + cached = self._getsub(rangeid) + if cached is not None: + return cached + value = self._subranges(repo, rangeid) + self._setsub(rangeid, value) + return value + + def _getsub(self, rev): + """utility function used to access the subranges cache + + This mostly exist to help the on disk persistence""" + return self._subrangescache.get(rev) + + def _setsub(self, rev, value): + """utility function used to set the subranges cache + + This mostly exist to help the on disk persistence.""" + self._subrangescache[rev] = value + +class stablerange_mergepoint(stablerangecached): """Stablerange implementation using 'mergepoint' based sorting """ def __init__(self): - self._sortcache = stablesort.stablesortcache() super(stablerange_mergepoint, self).__init__() - def _sortfunction(self, repo, headrev): - return self._sortcache.get(repo, headrev) + def warmup(self, repo, upto=None): + # no cache to warm for basic implementation + pass def revsfromrange(self, repo, rangeid): """return revision contained in a range @@ -324,7 +354,208 @@ <head>, skipping the <index>th lower revisions. """ limit = self.rangelength(repo, rangeid) - return self._sortcache.get(repo, rangeid[0], limit=limit) + return repo.stablesort.get(repo, rangeid[0], limit=limit) + + def _stableparent(self, repo, headrev): + """The parent of the changeset with reusable subrange + + For non-merge it is simple, there is a single parent. For Mercurial we + have to find the right one. Since the stable sort use merge-point, we + know that one of REV parents stable sort is a subset of REV stable + sort. In other word: + + sort(::REV) = sort(::min(parents(REV)) + + sort(only(max(parents(REV)), min(parents(REV))) + + [REV] + + We are looking for that `min(parents(REV))`. Since the subrange are + based on the sort, we can reuse its subrange as well. + """ + ps = filterparents(repo.changelog.parentrevs(headrev)) + if not ps: + return nodemod.nullrev + elif len(ps) == 1: + return ps[0] + else: + tiebreaker = stablesort._mergepoint_tie_breaker(repo) + return min(ps, key=tiebreaker) + + def _parentrange(self, repo, rangeid): + stable_parent = self._stableparent(repo, rangeid[0]) + stable_parent_depth = self.depthrev(repo, stable_parent) + stable_parent_range = (stable_parent, rangeid[1]) + return stable_parent_depth, stable_parent_range + + def _warmcachefor(self, repo, rangeid, slicepoint): + """warm cache with all the element necessary""" + stack = [] + depth, current = self._parentrange(repo, rangeid) + while current not in self._subrangescache and slicepoint < depth: + stack.append(current) + depth, current = self._parentrange(repo, current) + while stack: + current = stack.pop() + self.subranges(repo, current) + + def _subranges(self, repo, rangeid): + headrev, initial_index = rangeid + # size 1 range can't be sliced + if self.rangelength(repo, rangeid) == 1: + return [] + # find were we need to slice + slicepoint = self._slicepoint(repo, rangeid) + + self._warmcachefor(repo, rangeid, slicepoint) + + stable_parent_data = self._parentrange(repo, rangeid) + stable_parent_depth, stable_parent_range = stable_parent_data + + # top range is always the same, so we can build it early for all + top_range = (headrev, slicepoint) + + # now find out about the lower range, if we are lucky there is only + # one, otherwise we need to issue multiple one to cover every revision + # on the lower set. (and cover them only once). + if slicepoint == stable_parent_depth: + # luckly shot, the parent is actually the head of the lower range + subranges = [ + stable_parent_range, + top_range, + ] + elif slicepoint < stable_parent_depth: + # The parent is above the slice point, + # it's lower subrange will be the same so we just get them, + # (and the top range is always the same) + subranges = self.subranges(repo, stable_parent_range)[:-1] + subranges.append(top_range) + elif initial_index < stable_parent_depth < slicepoint: + # the parent is below the range we are considering, we need to + # compute these uniques subranges + subranges = [stable_parent_range] + subranges.extend(self._unique_subranges(repo, headrev, + stable_parent_depth, + slicepoint)) + subranges.append(top_range) + else: + # we cannot reuse the parent range at all + subranges = list(self._unique_subranges(repo, headrev, + initial_index, + slicepoint)) + subranges.append(top_range) + + return subranges + + def _unique_subranges(self, repo, headrev, initial_index, slicepoint): + """Compute subrange unique to the exclusive part of merge""" + result = [] + depth = repo.depthcache.get + nextmerge = repo.firstmergecache.get + walkfrom = functools.partial(repo.stablesort.walkfrom, repo) + getjumps = functools.partial(repo.stablesort.getjumps, repo) + skips = depth(headrev) - slicepoint + tomap = slicepoint - initial_index + + jumps = getjumps(headrev) + # this function is only caled if headrev is a merge + # and initial_index is above its lower parents + assert jumps is not None + jumps = iter(jumps) + assert 0 < skips, skips + assert 0 < tomap, (tomap, (headrev, initial_index), slicepoint) + + # utility function to find the next changeset with jump information + # (and the distance to it) + def nextmergedata(startrev): + merge = nextmerge(startrev) + depthrev = depth(startrev) + if merge == startrev: + return 0, startrev + elif merge == nodemod.nullrev: + return depthrev, None + depthmerge = depth(merge) + return depthrev - depthmerge, merge + + # skip over all necesary data + mainjump = None + jumpdest = headrev + while 0 < skips: + jumphead = jumpdest + currentjump = next(jumps) + skipped = size = currentjump[2] + jumpdest = currentjump[1] + if size == skips: + jumphead = jumpdest + mainjump = next(jumps) + mainsize = mainjump[2] + elif skips < size: + revs = walkfrom(jumphead) + next(revs) + for i in xrange(skips): + jumphead = next(revs) + assert jumphead is not None + skipped = skips + size -= skips + mainjump = currentjump + mainsize = size + skips -= skipped + assert skips == 0, skips + + # exiting from the previous block we should have: + # jumphead: first non-skipped revision (head of the high subrange) + # mainjump: next jump coming jump on main iteration + # mainsize: len(mainjump[0]::jumphead) + + # Now we need to compare walk on the main iteration with walk from the + # current subrange head. Instead of doing a full walk, we just skim + # over the jumps for each iteration. + rangehead = jumphead + refjumps = None + size = 0 + while size < tomap: + assert mainjump is not None + if refjumps is None: + dist2merge, merge = nextmergedata(jumphead) + if (mainsize <= dist2merge) or merge is None: + refjumps = iter(()) + ref = None + else: + # advance counters + size += dist2merge + mainsize -= dist2merge + jumphead = merge + refjumps = iter(getjumps(merge)) + ref = next(refjumps, None) + elif ref is not None and mainjump[0:2] == ref[0:2]: + # both follow the same path + size += mainsize + jumphead = mainjump[1] + mainjump = next(jumps, None) + mainsize = mainjump[2] + ref = next(refjumps, None) + if ref is None: + # we are doing with section specific to the last merge + # reset `refjumps` to trigger the logic that search for the + # next merge + refjumps = None + else: + size += mainsize + if size < tomap: + subrange = (rangehead, depth(rangehead) - size) + assert subrange[1] < depth(subrange[0]) + result.append(subrange) + tomap -= size + size = 0 + jumphead = rangehead = mainjump[1] + mainjump = next(jumps, None) + mainsize = mainjump[2] + refjumps = None + + if tomap: + subrange = (rangehead, depth(rangehead) - tomap) + assert subrange[1] < depth(subrange[0]), (rangehead, depth(rangehead), tomap) + result.append(subrange) + result.reverse() + return result class stablerange(stablerangecached): @@ -332,8 +563,6 @@ # The point up to which we have data in cache self._tiprev = None self._tipnode = None - # cache the standard stable subranges or a range - self._subrangescache = {} # To slices merge, we need to walk their descendant in reverse stable # sort order. For now we perform a full stable sort their descendant # and then use the relevant top most part. This order is going to be @@ -350,6 +579,7 @@ # computed from that point to compute some of the subranges from the # merge. self._inheritancecache = {} + super(stablerange, self).__init__() def warmup(self, repo, upto=None): """warm the cache up""" @@ -560,10 +790,12 @@ This function also have the important task to update the revscache of the parent rev s if possible and needed""" - p1, p2 = self._parents(rangeid[0], repo.changelog.parentrevs) - if p2 == nodemod.nullrev: + ps = filterparents(self._parents(rangeid[0], repo.changelog.parentrevs)) + if not ps: + return None + elif len(ps) == 1: # regular changesets, we pick the parent - reusablerev = p1 + reusablerev = ps[0] else: # merge, we try the inheritance point # if it is too low, it will be ditched by the depth check anyway @@ -583,9 +815,9 @@ return reurange def _slicesrangeat(self, repo, rangeid, globalindex): - p1, p2 = self._parents(rangeid[0], repo.changelog.parentrevs) - if p2 == nodemod.nullrev: - reuserev = p1 + ps = self._parents(rangeid[0], repo.changelog.parentrevs) + if len(ps) == 1: + reuserev = ps[0] else: index, reuserev = self._inheritancepoint(repo, rangeid[0]) if index < globalindex: @@ -642,225 +874,3 @@ top = (rangeid[0], globalindex) result.append(top) return result - -############################# -### simple sqlite caching ### -############################# - -_sqliteschema = [ - """CREATE TABLE meta(schemaversion INTEGER NOT NULL, - tiprev INTEGER NOT NULL, - tipnode BLOB NOT NULL - );""", - """CREATE TABLE range(rev INTEGER NOT NULL, - idx INTEGER NOT NULL, - PRIMARY KEY(rev, idx));""", - """CREATE TABLE subranges(listidx INTEGER NOT NULL, - suprev INTEGER NOT NULL, - supidx INTEGER NOT NULL, - subrev INTEGER NOT NULL, - subidx INTEGER NOT NULL, - PRIMARY KEY(listidx, suprev, supidx), - FOREIGN KEY (suprev, supidx) REFERENCES range(rev, idx), - FOREIGN KEY (subrev, subidx) REFERENCES range(rev, idx) - );""", - "CREATE INDEX subranges_index ON subranges (suprev, supidx);", - "CREATE INDEX range_index ON range (rev, idx);", -] -_newmeta = "INSERT INTO meta (schemaversion, tiprev, tipnode) VALUES (?,?,?);" -_updatemeta = "UPDATE meta SET tiprev = ?, tipnode = ?;" -_updaterange = "INSERT INTO range(rev, idx) VALUES (?,?);" -_updatesubranges = """INSERT - INTO subranges(listidx, suprev, supidx, subrev, subidx) - VALUES (?,?,?,?,?);""" -_queryexist = "SELECT name FROM sqlite_master WHERE type='table' AND name='meta';" -_querymeta = "SELECT schemaversion, tiprev, tipnode FROM meta;" -_queryrange = "SELECT * FROM range WHERE (rev = ? AND idx = ?);" -_querysubranges = """SELECT subrev, subidx - FROM subranges - WHERE (suprev = ? AND supidx = ?) - ORDER BY listidx;""" - -class sqlstablerange(stablerange): - - _schemaversion = 1 - - def __init__(self, repo): - lrusize = repo.ui.configint('experimental', 'obshashrange.lru-size', - 2000) - super(sqlstablerange, self).__init__(lrusize=lrusize) - self._vfs = repo.vfs - self._path = repo.vfs.join('cache/evoext_stablerange_v1.sqlite') - self._cl = repo.unfiltered().changelog # (okay to keep an old one) - self._ondisktiprev = None - self._ondisktipnode = None - self._unsavedsubranges = {} - - def warmup(self, repo, upto=None): - self._con # make sure the data base is loaded - try: - # samelessly lock the repo to ensure nobody will update the repo - # concurently. This should not be too much of an issue if we warm - # at the end of the transaction. - # - # XXX However, we lock even if we are up to date so we should check - # before locking - with repo.lock(): - super(sqlstablerange, self).warmup(repo, upto) - self._save(repo) - except error.LockError: - # Exceptionnally we are noisy about it since performance impact is - # large We should address that before using this more widely. - repo.ui.warn('stable-range cache: unable to lock repo while warming\n') - repo.ui.warn('(cache will not be saved)\n') - super(sqlstablerange, self).warmup(repo, upto) - - def _getsub(self, rangeid): - cache = self._subrangescache - if rangeid not in cache and rangeid[0] <= self._ondisktiprev and self._con is not None: - value = None - result = self._con.execute(_queryrange, rangeid).fetchone() - if result is not None: # database know about this node (skip in the future?) - value = self._con.execute(_querysubranges, rangeid).fetchall() - # in memory caching of the value - cache[rangeid] = value - return cache.get(rangeid) - - def _setsub(self, rangeid, value): - assert rangeid not in self._unsavedsubranges - self._unsavedsubranges[rangeid] = value - super(sqlstablerange, self)._setsub(rangeid, value) - - def _db(self): - try: - util.makedirs(self._vfs.dirname(self._path)) - except OSError: - return None - con = sqlite3.connect(self._path) - con.text_factory = str - return con - - @util.propertycache - def _con(self): - con = self._db() - if con is None: - return None - cur = con.execute(_queryexist) - if cur.fetchone() is None: - return None - meta = con.execute(_querymeta).fetchone() - if meta is None: - return None - if meta[0] != self._schemaversion: - return None - if len(self._cl) <= meta[1]: - return None - if self._cl.node(meta[1]) != meta[2]: - return None - self._ondisktiprev = meta[1] - self._ondisktipnode = meta[2] - if self._tiprev < self._ondisktiprev: - self._tiprev = self._ondisktiprev - self._tipnode = self._ondisktipnode - return con - - def _save(self, repo): - repo = repo.unfiltered() - repo.depthcache.save(repo) - if not self._unsavedsubranges: - return # no new data - - if self._con is None: - util.unlinkpath(self._path, ignoremissing=True) - if '_con' in vars(self): - del self._con - - con = self._db() - if con is None: - return - with con: - for req in _sqliteschema: - con.execute(req) - - meta = [self._schemaversion, - self._tiprev, - self._tipnode, - ] - con.execute(_newmeta, meta) - else: - con = self._con - meta = con.execute(_querymeta).fetchone() - if meta[2] != self._ondisktipnode or meta[1] != self._ondisktiprev: - # drifting is currently an issue because this means another - # process might have already added the cache line we are about - # to add. This will confuse sqlite - msg = _('stable-range cache: skipping write, ' - 'database drifted under my feet\n') - hint = _('(disk: %s-%s vs mem: %s%s)\n') - data = (meta[2], meta[1], self._ondisktiprev, self._ondisktipnode) - repo.ui.warn(msg) - repo.ui.warn(hint % data) - return - meta = [self._tiprev, - self._tipnode, - ] - con.execute(_updatemeta, meta) - - self._saverange(con, repo) - con.commit() - self._ondisktiprev = self._tiprev - self._ondisktipnode = self._tipnode - self._unsavedsubranges.clear() - - def _saverange(self, con, repo): - repo = repo.unfiltered() - data = [] - allranges = set() - for key, value in self._unsavedsubranges.items(): - allranges.add(key) - for idx, sub in enumerate(value): - data.append((idx, key[0], key[1], sub[0], sub[1])) - - con.executemany(_updaterange, allranges) - con.executemany(_updatesubranges, data) - - -@eh.reposetup -def setupcache(ui, repo): - - class stablerangerepo(repo.__class__): - - @localrepo.unfilteredpropertycache - def stablerange(self): - return sqlstablerange(repo) - - @localrepo.unfilteredmethod - def destroyed(self): - if 'stablerange' in vars(self): - del self.stablerange - super(stablerangerepo, self).destroyed() - - def transaction(self, *args, **kwargs): - tr = super(stablerangerepo, self).transaction(*args, **kwargs) - if not repo.ui.configbool('experimental', 'obshashrange', False): - return tr - if not repo.ui.configbool('experimental', 'obshashrange.warm-cache', - True): - return tr - maxrevs = self.ui.configint('experimental', 'obshashrange.max-revs', None) - if maxrevs is not None and maxrevs < len(self.unfiltered()): - return tr - reporef = weakref.ref(self) - - def _warmcache(tr): - repo = reporef() - if repo is None: - return - if 'node' in tr.hookargs: - # new nodes ! - repo.stablerange.warmup(repo) - - tr.addpostclose('warmcache-10-stablerange', _warmcache) - return tr - - repo.__class__ = stablerangerepo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/stablerangecache.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,392 @@ +# Code dedicated to the caching of "stable ranges" +# +# These stable ranges are use for obsolescence markers discovery +# +# Copyright 2017 Pierre-Yves David <pierre-yves.david@ens-lyon.org> +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +import abc +import heapq +import sqlite3 +import time +import weakref + +from mercurial import ( + error, + localrepo, + util, +) + +from . import ( + exthelper, + genericcaches, + stablerange, + utility, +) + +from mercurial.i18n import _ + +eh = exthelper.exthelper() +eh.merge(stablerange.eh) + +class stablerangeondiskbase(stablerange.stablerangecached, + genericcaches.changelogsourcebase): + """combine the generic stablerange cache usage with generic changelog one + """ + + def _updatefrom(self, repo, data): + """compute the rev of one revision, assert previous revision has an hot cache + """ + repo = repo.unfiltered() + ui = repo.ui + + rangeheap = [] + for r in data: + rangeheap.append((r, 0)) + total = len(data) + + heappop = heapq.heappop + heappush = heapq.heappush + heapify = heapq.heapify + + original = set(rangeheap) + seen = 0 + # progress report is showing up in the profile for small and fast + # repository so we only update it every so often + progress_each = 100 + progress_last = time.time() + heapify(rangeheap) + while rangeheap: + rangeid = heappop(rangeheap) + if rangeid in original: + if not seen % progress_each: + # if a lot of time passed, report more often + progress_new = time.time() + if (1 < progress_each) and (0.1 < progress_new - progress_last): + progress_each /= 10 + ui.progress(_("filling stablerange cache"), seen, total=total) + progress_last = progress_new + seen += 1 + original.remove(rangeid) # might have been added from other source + rangeid = rangeid + if self._getsub(rangeid) is None: + for sub in self.subranges(repo, rangeid): + if self._getsub(sub) is None: + heappush(rangeheap, sub) + ui.progress(_("filling stablerange cache"), None, total=total) + + def clear(self, reset=False): + super(stablerangeondiskbase, self).clear() + self._subrangescache.clear() + +############################# +### simple sqlite caching ### +############################# + +_sqliteschema = [ + """CREATE TABLE meta(schemaversion INTEGER NOT NULL, + tiprev INTEGER NOT NULL, + tipnode BLOB NOT NULL + );""", + """CREATE TABLE range(rev INTEGER NOT NULL, + idx INTEGER NOT NULL, + PRIMARY KEY(rev, idx));""", + """CREATE TABLE subranges(listidx INTEGER NOT NULL, + suprev INTEGER NOT NULL, + supidx INTEGER NOT NULL, + subrev INTEGER NOT NULL, + subidx INTEGER NOT NULL, + PRIMARY KEY(listidx, suprev, supidx), + FOREIGN KEY (suprev, supidx) REFERENCES range(rev, idx), + FOREIGN KEY (subrev, subidx) REFERENCES range(rev, idx) + );""", + "CREATE INDEX subranges_index ON subranges (suprev, supidx);", + "CREATE INDEX superranges_index ON subranges (subrev, subidx);", + "CREATE INDEX range_index ON range (rev, idx);", +] +_newmeta = "INSERT INTO meta (schemaversion, tiprev, tipnode) VALUES (?,?,?);" +_updatemeta = "UPDATE meta SET tiprev = ?, tipnode = ?;" +_updaterange = "INSERT INTO range(rev, idx) VALUES (?,?);" +_updatesubranges = """INSERT + INTO subranges(listidx, suprev, supidx, subrev, subidx) + VALUES (?,?,?,?,?);""" +_queryexist = "SELECT name FROM sqlite_master WHERE type='table' AND name='meta';" +_querymeta = "SELECT schemaversion, tiprev, tipnode FROM meta;" +_queryrange = "SELECT * FROM range WHERE (rev = ? AND idx = ?);" +_querysubranges = """SELECT subrev, subidx + FROM subranges + WHERE (suprev = ? AND supidx = ?) + ORDER BY listidx;""" +_querysuperranges = """SELECT suprev, supidx + FROM subranges + WHERE (subrev = ? AND subidx = ?) + ORDER BY listidx;""" + +class stablerangesqlbase(stablerange.stablerangecached): + """class that can handle all the bits needed to store range into sql + """ + + __metaclass__ = abc.ABCMeta + + _schemaversion = None + _cachefile = None + + def __init__(self, repo, **kwargs): + super(stablerangesqlbase, self).__init__(**kwargs) + self._vfs = repo.vfs + self._path = repo.vfs.join(self._cachefile) + self._cl = repo.unfiltered().changelog # (okay to keep an old one) + self._ondisktiprev = None + self._ondisktipnode = None + self._unsavedsubranges = {} + + def contains(self, repo, revs): + new = set() + known = set() + depth = repo.depthcache.get + for r in revs: + new.add((r, depth(r) - 1)) + new.add((r, 0)) + con = self._con + while new and con is not None: + # many execute is not efficient + next = new.pop() + known.add(next) + ranges = set(con.execute(_querysuperranges, next).fetchall()) + new.update(ranges) + new -= known + return sorted(known) + + def _getsub(self, rangeid): + # 1) check the in memory cache + # 2) check the sqlcaches (and warm in memory cache we want we find) + cache = self._subrangescache + if rangeid not in cache and rangeid[0] <= self._ondisktiprev and self._con is not None: + value = None + result = self._con.execute(_queryrange, rangeid).fetchone() + if result is not None: # database know about this node (skip in the future?) + value = self._con.execute(_querysubranges, rangeid).fetchall() + # in memory caching of the value + cache[rangeid] = value + return cache.get(rangeid) + + def _setsub(self, rangeid, value): + assert rangeid not in self._unsavedsubranges + self._unsavedsubranges[rangeid] = value + super(stablerangesqlbase, self)._setsub(rangeid, value) + + def _db(self): + try: + util.makedirs(self._vfs.dirname(self._path)) + except OSError: + return None + con = sqlite3.connect(self._path) + con.text_factory = str + return con + + @util.propertycache + def _con(self): + con = self._db() + if con is None: + return None + cur = con.execute(_queryexist) + if cur.fetchone() is None: + return None + meta = con.execute(_querymeta).fetchone() + if meta is None: + return None + if meta[0] != self._schemaversion: + return None + if len(self._cl) <= meta[1]: + return None + if self._cl.node(meta[1]) != meta[2]: + return None + self._ondisktiprev = meta[1] + self._ondisktipnode = meta[2] + if self._tiprev < self._ondisktiprev: + self._tiprev = self._ondisktiprev + self._tipnode = self._ondisktipnode + return con + + def _save(self, repo): + repo = repo.unfiltered() + repo.depthcache.save(repo) + if not self._unsavedsubranges: + return # no new data + + if self._con is None: + util.unlinkpath(self._path, ignoremissing=True) + if '_con' in vars(self): + del self._con + + con = self._db() + if con is None: + return + con.execute('BEGIN IMMEDIATE;') + with con: + for req in _sqliteschema: + con.execute(req) + + meta = [self._schemaversion, + self._tiprev, + self._tipnode, + ] + con.execute(_newmeta, meta) + else: + con = self._con + con.execute('BEGIN IMMEDIATE;') + meta = con.execute(_querymeta).fetchone() + if meta[2] != self._ondisktipnode or meta[1] != self._ondisktiprev: + # drifting is currently an issue because this means another + # process might have already added the cache line we are about + # to add. This will confuse sqlite + msg = _('stable-range cache: skipping write, ' + 'database drifted under my feet\n') + hint = _('(disk: %s-%s vs mem: %s%s)\n') + data = (meta[2], meta[1], self._ondisktiprev, self._ondisktipnode) + repo.ui.warn(msg) + repo.ui.warn(hint % data) + con.execute('ROLLBACK;') + return + meta = [self._tiprev, + self._tipnode, + ] + con.execute(_updatemeta, meta) + + self._saverange(con, repo) + con.commit() + self._ondisktiprev = self._tiprev + self._ondisktipnode = self._tipnode + self._unsavedsubranges.clear() + + def _saverange(self, con, repo): + repo = repo.unfiltered() + data = [] + allranges = set() + for key, value in self._unsavedsubranges.items(): + allranges.add(key) + for idx, sub in enumerate(value): + data.append((idx, key[0], key[1], sub[0], sub[1])) + + con.executemany(_updaterange, allranges) + con.executemany(_updatesubranges, data) + +class stablerangesql(stablerangesqlbase, stablerangeondiskbase): + """base clase able to preserve data to disk as sql""" + + __metaclass__ = abc.ABCMeta + + # self._cachekey = (tiprev, tipnode) + + @property + def _tiprev(self): + return self._cachekey[0] + + @_tiprev.setter + def _tiprev(self, value): + self._cachekey = (value, self._cachekey[1]) + + @property + def _tipnode(self): + return self._cachekey[1] + + @_tipnode.setter + def _tipnode(self, value): + self._cachekey = (self._cachekey[0], value) + + def clear(self, reset=False): + super(stablerangesql, self).clear(reset=reset) + if '_con' in vars(self): + del self._con + self._subrangescache.clear() + + def load(self, repo): + """load data from disk""" + assert repo.filtername is None + self._cachekey = self.emptykey + + if self._con is not None: + self._cachekey = (self._ondisktiprev, self._ondisktipnode) + self._ondiskkey = self._cachekey + + def save(self, repo): + if self._cachekey is None or self._cachekey == self._ondiskkey: + return + self._save(repo) + +class mergepointsql(stablerangesql, stablerange.stablerange_mergepoint): + + _schemaversion = 2 + _cachefile = 'cache/evoext_stablerange_v2.sqlite' + _cachename = 'evo-ext-stablerange-mergepoint' + +class sqlstablerange(stablerangesqlbase, stablerange.stablerange): + + _schemaversion = 1 + _cachefile = 'cache/evoext_stablerange_v1.sqlite' + + def warmup(self, repo, upto=None): + self._con # make sure the data base is loaded + try: + # samelessly lock the repo to ensure nobody will update the repo + # concurently. This should not be too much of an issue if we warm + # at the end of the transaction. + # + # XXX However, we lock even if we are up to date so we should check + # before locking + with repo.lock(): + super(sqlstablerange, self).warmup(repo, upto) + self._save(repo) + except error.LockError: + # Exceptionnally we are noisy about it since performance impact is + # large We should address that before using this more widely. + repo.ui.warn('stable-range cache: unable to lock repo while warming\n') + repo.ui.warn('(cache will not be saved)\n') + super(sqlstablerange, self).warmup(repo, upto) + +@eh.reposetup +def setupcache(ui, repo): + + class stablerangerepo(repo.__class__): + + @localrepo.unfilteredpropertycache + def stablerange(self): + cache = mergepointsql(repo) + cache.update(repo) + return cache + + @localrepo.unfilteredmethod + def destroyed(self): + if 'stablerange' in vars(self): + self.stablerange.clear() + del self.stablerange + super(stablerangerepo, self).destroyed() + + if util.safehasattr(repo, 'updatecaches'): + @localrepo.unfilteredmethod + def updatecaches(self, tr=None): + if utility.shouldwarmcache(self, tr): + self.stablerange.update(self) + self.stablerange.save(self) + super(stablerangerepo, self).updatecaches(tr) + + else: + def transaction(self, *args, **kwargs): + tr = super(stablerangerepo, self).transaction(*args, **kwargs) + reporef = weakref.ref(self) + + def _warmcache(tr): + repo = reporef() + if repo is None: + return + repo = repo.unfiltered() + repo.stablerange.update(repo) + repo.stablerange.save(repo) + + if utility.shouldwarmcache(self, tr): + tr.addpostclose('warmcache-10stablerange', _warmcache) + return tr + + repo.__class__ = stablerangerepo
--- a/hgext3rd/evolve/stablesort.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/stablesort.py Tue Jan 16 04:35:34 2018 +0100 @@ -7,23 +7,33 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +import array import collections +import struct +import weakref from mercurial import ( commands, cmdutil, + localrepo, error, node as nodemod, scmutil, + util, ) from mercurial.i18n import _ from . import ( + compat, depthcache, exthelper, + utility, + genericcaches, ) +filterparents = utility.filterparents + eh = exthelper.exthelper() eh.merge(depthcache.eh) @@ -38,7 +48,12 @@ * number of jump points. * <insert-your-idea> """ - return repo.changelog.node + node = repo.changelog.node + depth = repo.depthcache.get + + def key(rev): + return (-depth(rev), node(rev)) + return key @eh.command( 'debugstablesort', @@ -97,10 +112,11 @@ # * we need to detect branching children = collections.defaultdict(list) for r in cl.ancestors(revs, inclusive=True): - p1, p2 = parents(r) - children[p1].append(r) - if p2 != nullrev: - children[p2].append(r) + ps = filterparents(parents(r)) + if not ps: + children[nullrev].append(r) + for p in ps: + children[p].append(r) # step two: walk back up # * pick lowest node in case of branching # * stack disregarded part of the branching @@ -108,7 +124,7 @@ # track what changeset has been seen = [0] * (max(revs) + 2) - seen[-1] = True # nullrev is known + seen[nullrev] = True # nullrev is known # starts from repository roots # reuse the list form the mapping as we won't need it again anyway stack = children[nullrev] @@ -128,8 +144,8 @@ if seen[current]: current = None continue - p1, p2 = parents(current) - if not (seen[p1] and seen[p2]): + ps = filterparents(parents(current)) + if not all(seen[p] for p in ps): # we can't iterate on this merge yet because other child is not # yielded yet (and we are topo sorting) we can discard it for now # because it will be reached from the other child. @@ -138,7 +154,7 @@ assert not seen[current] seen[current] = True result.append(current) # could be yield, cf earlier comment - if mergecallback is not None and p2 != nullrev: + if mergecallback is not None and 2 <= len(ps): mergecallback(result, current) cs = children[current] if not cs: @@ -199,15 +215,14 @@ children = collections.defaultdict(set) parentmap = {} for r in revs: - p1, p2 = parents(r) - children[p1].add(r) - if p2 != nullrev: - children[p2].add(r) - parentmap[r] = tuple(sorted((p1, p2), key=tiebreaker)) - elif p1 != nullrev: - parentmap[r] = (p1,) - else: - parentmap[r] = () + ps = filterparents(parents(r)) + if 2 <= len(ps): + ps = tuple(sorted(ps, key=tiebreaker)) + parentmap[r] = ps + for p in ps: + children[p].add(r) + if not ps: + children[nullrev].add(r) # step two: walk again, stack = [head] resultset = set() @@ -272,13 +287,13 @@ mid = [] bottom = [] - ps = [p for p in parents(head) if p is not nodemod.nullrev] + ps = filterparents(parents(head)) while len(ps) == 1: top.append(ps[0]) - ps = [p for p in parents(ps[0]) if p is not nodemod.nullrev] + ps = filterparents(parents(ps[0])) top.reverse() if len(ps) == 2: - ps.sort(key=tiebreaker) + ps = sorted(ps, key=tiebreaker) # get the part from the highest parent. This is the part that changes mid_revs = repo.revs('only(%d, %d)', ps[1], ps[0]) @@ -286,8 +301,7 @@ mid = stablesort_mergepoint_bounded(repo, ps[1], mid_revs) # And follow up with part othe parent we can inherit from - bottom_revs = cl.ancestors([ps[0]], inclusive=True) - bottom = stablesort_mergepoint_bounded(repo, ps[0], bottom_revs) + bottom = stablesort_mergepoint_head(repo, ps[0]) return bottom + mid + top @@ -300,34 +314,96 @@ % len(heads)) head = heads.first() cache = stablesortcache() - return cache.get(repo, head, limit=limit) + first = list(cache.get(repo, head, limit=limit)) + second = list(cache.get(repo, head, limit=limit)) + if first != second: + repo.ui.warn('stablesort-cache: initial run different from re-run:\n' + ' %s\n' + ' %s\n' % (first, second)) + return second class stablesortcache(object): + def __init__(self): + self._jumps = {} + super(stablesortcache, self).__init__() + def get(self, repo, rev, limit=None): result = [] - for r in self._revsfrom(repo, rev): + for r in self.walkfrom(repo, rev): result.append(r) if limit is not None and limit <= len(result): break result.reverse() return result - def _revsfrom(self, repo, head): + def getjumps(self, repo, rev): + if not self._hasjumpsdata(rev): + parents = filterparents(repo.changelog.parentrevs(rev)) + if len(parents) <= 1: + self._setjumps(rev, None) + else: + # merge ! warn the cache + tiebreaker = _mergepoint_tie_breaker(repo) + minparent = sorted(parents, key=tiebreaker)[0] + for r in self.walkfrom(repo, rev): + if r == minparent: + break + return self._getjumps(rev) + + def _hasjumpsdata(self, rev): + return rev in self._jumps + + def _getjumps(self, rev): + return self._jumps.get(rev) + + def _setjumps(self, rev, jumps): + self._jumps[rev] = jumps + + def walkfrom(self, repo, head): tiebreaker = _mergepoint_tie_breaker(repo) cl = repo.changelog parentsfunc = cl.parentrevs def parents(rev): - return [p for p in parentsfunc(rev) if p is not nodemod.nullrev] + return filterparents(parentsfunc(rev)) + + def oneparent(rev): + ps = parents(rev) + if not ps: + return None + if len(ps) == 1: + return ps[0] + return max(ps, key=tiebreaker) current = head - previous_current = None + previous_current_1 = object() + previous_current_2 = object() while current is not None: - assert current is not previous_current + previous_current_2 = previous_current_1 + previous_current_1 = current + assert previous_current_1 is not previous_current_2 + + jumps = self._getjumps(current) + if jumps is not None: + # we have enough cached information to directly iterate over + # the exclusive size. + for j in jumps: + jump_point = j[0] + jump_dest = j[1] + if current == jump_point: + yield current + else: + while current != jump_point: + yield current + current = oneparent(current) + assert current is not None + yield current + current = jump_dest + continue + yield current - previous_current = current ps = parents(current) if not ps: @@ -337,54 +413,290 @@ elif len(ps) == 2: lower_parent, higher_parent = sorted(ps, key=tiebreaker) - for rev in self._process_exclusive_side(lower_parent, - higher_parent, - cl.findmissingrevs, - parents, - tiebreaker): + rev = current + jumps = [] + + def recordjump(source, destination, size): + jump = (source, destination, size) + jumps.append(jump) + process = self._process_exclusive_side + for rev in process(lower_parent, higher_parent, cl, parents, + tiebreaker, recordjump): yield rev + if rev == current: + recordjump(rev, lower_parent, 1) + + self._setjumps(current, jumps) + current = lower_parent - def _process_exclusive_side(self, lower, higher, findmissingrevs, parents, tiebreaker): + def _process_exclusive_side(self, lower, higher, cl, parents, tiebreaker, + recordjump): + + exclusive = cl.findmissingrevs(common=[lower], heads=[higher]) - exclusive = findmissingrevs(common=[lower], - heads=[higher]) + def popready(stack): + """pop the top most ready item in the list""" + for idx in xrange(len(stack) - 1, -1, -1): + if children[stack[idx]].issubset(seen): + return stack.pop(idx) + return None - stack = [] + hardstack = [] + previous = None seen = set() + current = higher children = collections.defaultdict(set) - if not exclusive: - current = None - else: - current = higher - bound = set(exclusive) + bound = set(exclusive) + if exclusive: for r in exclusive: for p in parents(r): children[p].add(r) - previous_current = None - while current is not None: - assert current is not previous_current - yield current - seen.add(current) - previous_current = current + hardstack.append(higher) + nextjump = False + size = 1 # take the merge point into account + while hardstack: + current = popready(hardstack) + if current in seen: + continue + softstack = [] + while current in bound and current not in seen: + if nextjump: + recordjump(previous, current, size) + nextjump = False + size = 0 + yield current + size += 1 + previous = current + seen.add(current) + + all_parents = parents(current) + + # search or next parent to walk through + fallback, next = None, None + if 1 == len(all_parents): + next = all_parents[0] + elif 2 <= len(all_parents): + fallback, next = sorted(all_parents, key=tiebreaker) + + # filter parent not ready (children not emitted) + while next is not None and not children[next].issubset(seen): + nextjump = True + next = fallback + fallback = None + + # stack management + if next is None: + next = popready(softstack) + if next is not None: + nextjump = True + elif fallback is not None: + softstack.append(fallback) + + # get ready for next iteration + current = next + + # any in processed head has to go in the hard stack + nextjump = True + hardstack.extend(softstack) + + if previous is not None: + recordjump(previous, lower, size) - ps = parents(current) +def stablesort_mergepoint_head_ondisk(repo, revs, limit=None): + heads = repo.revs('heads(%ld)', revs) + if not heads: + return [] + elif 2 < len(heads): + raise error.Abort('cannot use head based merging, %d heads found' + % len(heads)) + head = heads.first() + unfi = repo.unfiltered() + cache = unfi.stablesort + cache.save(unfi) + return cache.get(repo, head, limit=limit) + +S_INDEXSIZE = struct.Struct('>I') + +class ondiskstablesortcache(stablesortcache, genericcaches.changelogsourcebase): + + _filepath = 'evoext-stablesortcache-00' + _cachename = 'evo-ext-stablesort' + + def __init__(self): + super(ondiskstablesortcache, self).__init__() + self._index = array.array('l') + self._data = array.array('l') + del self._jumps + + def getjumps(self, repo, rev): + if len(self._index) < rev: + msg = 'stablesortcache must be warmed before use (%d < %d)' + msg %= (len(self._index), rev) + raise error.ProgrammingError(msg) + return self._getjumps(rev) + + def _getjumps(self, rev): + # very first revision + if rev == 0: + return None + # no data yet + if len(self._index) <= rev: + return None + index = self._index + # non merge revision + if index[rev] == index[rev - 1]: + return None + data = self._data + # merge revision + + def jumps(): + for idx in xrange(index[rev - 1], index[rev]): + i = idx * 3 + yield tuple(data[i:i + 3]) + return jumps() + + def _setjumps(self, rev, jumps): + assert len(self._index) == rev, (len(self._index), rev) + if rev == 0: + self._index.append(0) + return + end = self._index[rev - 1] + if jumps is None: + self._index.append(end) + return + assert len(self._data) == end * 3, (len(self._data), end) + for j in jumps: + self._data.append(j[0]) + self._data.append(j[1]) + self._data.append(j[2]) + end += 1 + self._index.append(end) - usable_parents = [p for p in ps - if (p in bound and children[p].issubset(seen))] - if not usable_parents: - if stack: - current = stack.pop() - else: - current = None - elif len(usable_parents) == 1: - current = usable_parents[0] + def _updatefrom(self, repo, data): + repo = repo.unfiltered() + + total = len(data) + + def progress(pos, rev): + repo.ui.progress('updating stablesort cache', + pos, 'rev %s' % rev, unit='revision', total=total) + + progress(0, '') + for idx, rev in enumerate(data): + parents = filterparents(repo.changelog.parentrevs(rev)) + if len(parents) <= 1: + self._setjumps(rev, None) else: - lower_parent, higher_parent = sorted(usable_parents, key=tiebreaker) - stack.append(lower_parent) - current = higher_parent + # merge! warn the cache + tiebreaker = _mergepoint_tie_breaker(repo) + minparent = sorted(parents, key=tiebreaker)[0] + for r in self.walkfrom(repo, rev): + if r == minparent: + break + if not (idx % 1000): # progress as a too high performance impact + progress(idx, rev) + progress(None, '') + + def clear(self, reset=False): + super(ondiskstablesortcache, self).clear() + self._index = array.array('l') + self._data = array.array('l') + + def load(self, repo): + """load data from disk + + (crude version, read everything all the time) + """ + assert repo.filtername is None + + cachevfs = compat.getcachevfs(repo) + data = cachevfs.tryread(self._filepath) + self._index = array.array('l') + self._data = array.array('l') + if not data: + self._cachekey = self.emptykey + else: + headerdata = data[:self._cachekeysize] + self._cachekey = self._deserializecachekey(headerdata) + offset = self._cachekeysize + indexsizedata = data[offset:offset + S_INDEXSIZE.size] + indexsize = S_INDEXSIZE.unpack(indexsizedata)[0] + offset += S_INDEXSIZE.size + self._index.fromstring(data[offset:offset + indexsize]) + offset += indexsize + self._data.fromstring(data[offset:]) + self._ondiskkey = self._cachekey + pass + + def save(self, repo): + """save the data to disk + + (crude version, rewrite everything all the time) + """ + if self._cachekey is None or self._cachekey == self._ondiskkey: + return + cachevfs = compat.getcachevfs(repo) + cachefile = cachevfs(self._filepath, 'w', atomictemp=True) + + # data to write + headerdata = self._serializecachekey() + indexdata = self._index.tostring() + data = self._data.tostring() + indexsize = S_INDEXSIZE.pack(len(indexdata)) + + # writing + cachefile.write(headerdata) + cachefile.write(indexsize) + cachefile.write(indexdata) + cachefile.write(data) + cachefile.close() + +@eh.reposetup +def setupcache(ui, repo): + + class stablesortrepo(repo.__class__): + + @localrepo.unfilteredpropertycache + def stablesort(self): + cache = ondiskstablesortcache() + cache.update(self) + return cache + + @localrepo.unfilteredmethod + def destroyed(self): + if 'stablesort' in vars(self): + self.stablesort.clear() + super(stablesortrepo, self).destroyed() + + if util.safehasattr(repo, 'updatecaches'): + @localrepo.unfilteredmethod + def updatecaches(self, tr=None): + if utility.shouldwarmcache(self, tr): + self.stablesort.update(self) + self.stablesort.save(self) + super(stablesortrepo, self).updatecaches(tr) + + else: + def transaction(self, *args, **kwargs): + tr = super(stablesortrepo, self).transaction(*args, **kwargs) + reporef = weakref.ref(self) + + def _warmcache(tr): + repo = reporef() + if repo is None: + return + repo = repo.unfiltered() + repo.stablesort.update(repo) + repo.stablesort.save(repo) + + if utility.shouldwarmcache(self, tr): + tr.addpostclose('warmcache-02stablesort', _warmcache) + return tr + + repo.__class__ = stablesortrepo _methodmap = { 'branchpoint': stablesort_branchpoint, @@ -392,4 +704,5 @@ 'basic-headstart': stablesort_mergepoint_head_basic, 'headstart': stablesort_mergepoint_head_debug, 'headcached': stablesort_mergepoint_head_cached, + 'headondisk': stablesort_mergepoint_head_ondisk, }
--- a/hgext3rd/evolve/templatekw.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/templatekw.py Tue Jan 16 04:35:34 2018 +0100 @@ -57,6 +57,7 @@ precursors = repo.obsstore.predecessors stack = [nodeid] + seen = set(stack) while stack: current = stack.pop() @@ -65,6 +66,11 @@ for prec in currentpreccs: precnodeid = prec[0] + # Basic cycle protection + if precnodeid in seen: + continue + seen.add(precnodeid) + if precnodeid in repo: yield precnodeid else:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hgext3rd/evolve/thirdparty/cbor.py Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,523 @@ +#!python +# -*- Python -*- +# +# Copyright 2014-2015 Brian Olson +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import datetime +import re +import struct +import sys + +_IS_PY3 = sys.version_info[0] >= 3 + +if _IS_PY3: + from io import BytesIO as StringIO +else: + try: + from cStringIO import StringIO + except: + from StringIO import StringIO + + +CBOR_TYPE_MASK = 0xE0 # top 3 bits +CBOR_INFO_BITS = 0x1F # low 5 bits + + +CBOR_UINT = 0x00 +CBOR_NEGINT = 0x20 +CBOR_BYTES = 0x40 +CBOR_TEXT = 0x60 +CBOR_ARRAY = 0x80 +CBOR_MAP = 0xA0 +CBOR_TAG = 0xC0 +CBOR_7 = 0xE0 # float and other types + +CBOR_UINT8_FOLLOWS = 24 # 0x18 +CBOR_UINT16_FOLLOWS = 25 # 0x19 +CBOR_UINT32_FOLLOWS = 26 # 0x1a +CBOR_UINT64_FOLLOWS = 27 # 0x1b +CBOR_VAR_FOLLOWS = 31 # 0x1f + +CBOR_BREAK = 0xFF + +CBOR_FALSE = (CBOR_7 | 20) +CBOR_TRUE = (CBOR_7 | 21) +CBOR_NULL = (CBOR_7 | 22) +CBOR_UNDEFINED = (CBOR_7 | 23) # js 'undefined' value + +CBOR_FLOAT16 = (CBOR_7 | 25) +CBOR_FLOAT32 = (CBOR_7 | 26) +CBOR_FLOAT64 = (CBOR_7 | 27) + +CBOR_TAG_DATE_STRING = 0 # RFC3339 +CBOR_TAG_DATE_ARRAY = 1 # any number type follows, seconds since 1970-01-01T00:00:00 UTC +CBOR_TAG_BIGNUM = 2 # big endian byte string follows +CBOR_TAG_NEGBIGNUM = 3 # big endian byte string follows +CBOR_TAG_DECIMAL = 4 # [ 10^x exponent, number ] +CBOR_TAG_BIGFLOAT = 5 # [ 2^x exponent, number ] +CBOR_TAG_BASE64URL = 21 +CBOR_TAG_BASE64 = 22 +CBOR_TAG_BASE16 = 23 +CBOR_TAG_CBOR = 24 # following byte string is embedded CBOR data + +CBOR_TAG_URI = 32 +CBOR_TAG_BASE64URL = 33 +CBOR_TAG_BASE64 = 34 +CBOR_TAG_REGEX = 35 +CBOR_TAG_MIME = 36 # following text is MIME message, headers, separators and all +CBOR_TAG_CBOR_FILEHEADER = 55799 # can open a file with 0xd9d9f7 + +_CBOR_TAG_BIGNUM_BYTES = struct.pack('B', CBOR_TAG | CBOR_TAG_BIGNUM) + + +def dumps_int(val): + "return bytes representing int val in CBOR" + if val >= 0: + # CBOR_UINT is 0, so I'm lazy/efficient about not OR-ing it in. + if val <= 23: + return struct.pack('B', val) + if val <= 0x0ff: + return struct.pack('BB', CBOR_UINT8_FOLLOWS, val) + if val <= 0x0ffff: + return struct.pack('!BH', CBOR_UINT16_FOLLOWS, val) + if val <= 0x0ffffffff: + return struct.pack('!BI', CBOR_UINT32_FOLLOWS, val) + if val <= 0x0ffffffffffffffff: + return struct.pack('!BQ', CBOR_UINT64_FOLLOWS, val) + outb = _dumps_bignum_to_bytearray(val) + return _CBOR_TAG_BIGNUM_BYTES + _encode_type_num(CBOR_BYTES, len(outb)) + outb + val = -1 - val + return _encode_type_num(CBOR_NEGINT, val) + + +if _IS_PY3: + def _dumps_bignum_to_bytearray(val): + out = [] + while val > 0: + out.insert(0, val & 0x0ff) + val = val >> 8 + return bytes(out) +else: + def _dumps_bignum_to_bytearray(val): + out = [] + while val > 0: + out.insert(0, chr(val & 0x0ff)) + val = val >> 8 + return b''.join(out) + + +def dumps_float(val): + return struct.pack("!Bd", CBOR_FLOAT64, val) + + +_CBOR_TAG_NEGBIGNUM_BYTES = struct.pack('B', CBOR_TAG | CBOR_TAG_NEGBIGNUM) + + +def _encode_type_num(cbor_type, val): + """For some CBOR primary type [0..7] and an auxiliary unsigned number, return CBOR encoded bytes""" + assert val >= 0 + if val <= 23: + return struct.pack('B', cbor_type | val) + if val <= 0x0ff: + return struct.pack('BB', cbor_type | CBOR_UINT8_FOLLOWS, val) + if val <= 0x0ffff: + return struct.pack('!BH', cbor_type | CBOR_UINT16_FOLLOWS, val) + if val <= 0x0ffffffff: + return struct.pack('!BI', cbor_type | CBOR_UINT32_FOLLOWS, val) + if (((cbor_type == CBOR_NEGINT) and (val <= 0x07fffffffffffffff)) or + ((cbor_type != CBOR_NEGINT) and (val <= 0x0ffffffffffffffff))): + return struct.pack('!BQ', cbor_type | CBOR_UINT64_FOLLOWS, val) + if cbor_type != CBOR_NEGINT: + raise Exception("value too big for CBOR unsigned number: {0!r}".format(val)) + outb = _dumps_bignum_to_bytearray(val) + return _CBOR_TAG_NEGBIGNUM_BYTES + _encode_type_num(CBOR_BYTES, len(outb)) + outb + + +if _IS_PY3: + def _is_unicode(val): + return isinstance(val, str) +else: + def _is_unicode(val): + return isinstance(val, unicode) + + +def dumps_string(val, is_text=None, is_bytes=None): + if _is_unicode(val): + val = val.encode('utf8') + is_text = True + is_bytes = False + if (is_bytes) or not (is_text == True): + return _encode_type_num(CBOR_BYTES, len(val)) + val + return _encode_type_num(CBOR_TEXT, len(val)) + val + + +def dumps_array(arr, sort_keys=False): + head = _encode_type_num(CBOR_ARRAY, len(arr)) + parts = [dumps(x, sort_keys=sort_keys) for x in arr] + return head + b''.join(parts) + + +if _IS_PY3: + def dumps_dict(d, sort_keys=False): + head = _encode_type_num(CBOR_MAP, len(d)) + parts = [head] + if sort_keys: + for k in sorted(d.keys()): + v = d[k] + parts.append(dumps(k, sort_keys=sort_keys)) + parts.append(dumps(v, sort_keys=sort_keys)) + else: + for k,v in d.items(): + parts.append(dumps(k, sort_keys=sort_keys)) + parts.append(dumps(v, sort_keys=sort_keys)) + return b''.join(parts) +else: + def dumps_dict(d, sort_keys=False): + head = _encode_type_num(CBOR_MAP, len(d)) + parts = [head] + if sort_keys: + for k in sorted(d.iterkeys()): + v = d[k] + parts.append(dumps(k, sort_keys=sort_keys)) + parts.append(dumps(v, sort_keys=sort_keys)) + else: + for k,v in d.iteritems(): + parts.append(dumps(k, sort_keys=sort_keys)) + parts.append(dumps(v, sort_keys=sort_keys)) + return b''.join(parts) + + +def dumps_bool(b): + if b: + return struct.pack('B', CBOR_TRUE) + return struct.pack('B', CBOR_FALSE) + + +def dumps_tag(t, sort_keys=False): + return _encode_type_num(CBOR_TAG, t.tag) + dumps(t.value, sort_keys=sort_keys) + + +if _IS_PY3: + def _is_stringish(x): + return isinstance(x, (str, bytes)) + def _is_intish(x): + return isinstance(x, int) +else: + def _is_stringish(x): + return isinstance(x, (str, basestring, bytes, unicode)) + def _is_intish(x): + return isinstance(x, (int, long)) + + +def dumps(ob, sort_keys=False): + if ob is None: + return struct.pack('B', CBOR_NULL) + if isinstance(ob, bool): + return dumps_bool(ob) + if _is_stringish(ob): + return dumps_string(ob) + if isinstance(ob, (list, tuple)): + return dumps_array(ob, sort_keys=sort_keys) + # TODO: accept other enumerables and emit a variable length array + if isinstance(ob, dict): + return dumps_dict(ob, sort_keys=sort_keys) + if isinstance(ob, float): + return dumps_float(ob) + if _is_intish(ob): + return dumps_int(ob) + if isinstance(ob, Tag): + return dumps_tag(ob, sort_keys=sort_keys) + raise Exception("don't know how to cbor serialize object of type %s", type(ob)) + + +# same basic signature as json.dump, but with no options (yet) +def dump(obj, fp, sort_keys=False): + """ + obj: Python object to serialize + fp: file-like object capable of .write(bytes) + """ + # this is kinda lame, but probably not inefficient for non-huge objects + # TODO: .write() to fp as we go as each inner object is serialized + blob = dumps(obj, sort_keys=sort_keys) + fp.write(blob) + + +class Tag(object): + def __init__(self, tag=None, value=None): + self.tag = tag + self.value = value + + def __repr__(self): + return "Tag({0!r}, {1!r})".format(self.tag, self.value) + + def __eq__(self, other): + if not isinstance(other, Tag): + return False + return (self.tag == other.tag) and (self.value == other.value) + + +def loads(data): + """ + Parse CBOR bytes and return Python objects. + """ + if data is None: + raise ValueError("got None for buffer to decode in loads") + fp = StringIO(data) + return _loads(fp)[0] + + +def load(fp): + """ + Parse and return object from fp, a file-like object supporting .read(n) + """ + return _loads(fp)[0] + + +_MAX_DEPTH = 100 + + +def _tag_aux(fp, tb): + bytes_read = 1 + tag = tb & CBOR_TYPE_MASK + tag_aux = tb & CBOR_INFO_BITS + if tag_aux <= 23: + aux = tag_aux + elif tag_aux == CBOR_UINT8_FOLLOWS: + data = fp.read(1) + aux = struct.unpack_from("!B", data, 0)[0] + bytes_read += 1 + elif tag_aux == CBOR_UINT16_FOLLOWS: + data = fp.read(2) + aux = struct.unpack_from("!H", data, 0)[0] + bytes_read += 2 + elif tag_aux == CBOR_UINT32_FOLLOWS: + data = fp.read(4) + aux = struct.unpack_from("!I", data, 0)[0] + bytes_read += 4 + elif tag_aux == CBOR_UINT64_FOLLOWS: + data = fp.read(8) + aux = struct.unpack_from("!Q", data, 0)[0] + bytes_read += 8 + else: + assert tag_aux == CBOR_VAR_FOLLOWS, "bogus tag {0:02x}".format(tb) + aux = None + + return tag, tag_aux, aux, bytes_read + + +def _read_byte(fp): + tb = fp.read(1) + if len(tb) == 0: + # I guess not all file-like objects do this + raise EOFError() + return ord(tb) + + +def _loads_var_array(fp, limit, depth, returntags, bytes_read): + ob = [] + tb = _read_byte(fp) + while tb != CBOR_BREAK: + (subob, sub_len) = _loads_tb(fp, tb, limit, depth, returntags) + bytes_read += 1 + sub_len + ob.append(subob) + tb = _read_byte(fp) + return (ob, bytes_read + 1) + + +def _loads_var_map(fp, limit, depth, returntags, bytes_read): + ob = {} + tb = _read_byte(fp) + while tb != CBOR_BREAK: + (subk, sub_len) = _loads_tb(fp, tb, limit, depth, returntags) + bytes_read += 1 + sub_len + (subv, sub_len) = _loads(fp, limit, depth, returntags) + bytes_read += sub_len + ob[subk] = subv + tb = _read_byte(fp) + return (ob, bytes_read + 1) + + +if _IS_PY3: + def _loads_array(fp, limit, depth, returntags, aux, bytes_read): + ob = [] + for i in range(aux): + subob, subpos = _loads(fp) + bytes_read += subpos + ob.append(subob) + return ob, bytes_read + def _loads_map(fp, limit, depth, returntags, aux, bytes_read): + ob = {} + for i in range(aux): + subk, subpos = _loads(fp) + bytes_read += subpos + subv, subpos = _loads(fp) + bytes_read += subpos + ob[subk] = subv + return ob, bytes_read +else: + def _loads_array(fp, limit, depth, returntags, aux, bytes_read): + ob = [] + for i in xrange(aux): + subob, subpos = _loads(fp) + bytes_read += subpos + ob.append(subob) + return ob, bytes_read + def _loads_map(fp, limit, depth, returntags, aux, bytes_read): + ob = {} + for i in xrange(aux): + subk, subpos = _loads(fp) + bytes_read += subpos + subv, subpos = _loads(fp) + bytes_read += subpos + ob[subk] = subv + return ob, bytes_read + +def _loads(fp, limit=None, depth=0, returntags=False): + "return (object, bytes read)" + if depth > _MAX_DEPTH: + raise Exception("hit CBOR loads recursion depth limit") + + tb = _read_byte(fp) + + return _loads_tb(fp, tb, limit, depth, returntags) + +def _loads_tb(fp, tb, limit=None, depth=0, returntags=False): + # Some special cases of CBOR_7 best handled by special struct.unpack logic here + if tb == CBOR_FLOAT16: + data = fp.read(2) + hibyte, lowbyte = struct.unpack_from("BB", data, 0) + exp = (hibyte >> 2) & 0x1F + mant = ((hibyte & 0x03) << 8) | lowbyte + if exp == 0: + val = mant * (2.0 ** -24) + elif exp == 31: + if mant == 0: + val = float('Inf') + else: + val = float('NaN') + else: + val = (mant + 1024.0) * (2 ** (exp - 25)) + if hibyte & 0x80: + val = -1.0 * val + return (val, 3) + elif tb == CBOR_FLOAT32: + data = fp.read(4) + pf = struct.unpack_from("!f", data, 0) + return (pf[0], 5) + elif tb == CBOR_FLOAT64: + data = fp.read(8) + pf = struct.unpack_from("!d", data, 0) + return (pf[0], 9) + + tag, tag_aux, aux, bytes_read = _tag_aux(fp, tb) + + if tag == CBOR_UINT: + return (aux, bytes_read) + elif tag == CBOR_NEGINT: + return (-1 - aux, bytes_read) + elif tag == CBOR_BYTES: + ob, subpos = loads_bytes(fp, aux) + return (ob, bytes_read + subpos) + elif tag == CBOR_TEXT: + raw, subpos = loads_bytes(fp, aux, btag=CBOR_TEXT) + ob = raw.decode('utf8') + return (ob, bytes_read + subpos) + elif tag == CBOR_ARRAY: + if aux is None: + return _loads_var_array(fp, limit, depth, returntags, bytes_read) + return _loads_array(fp, limit, depth, returntags, aux, bytes_read) + elif tag == CBOR_MAP: + if aux is None: + return _loads_var_map(fp, limit, depth, returntags, bytes_read) + return _loads_map(fp, limit, depth, returntags, aux, bytes_read) + elif tag == CBOR_TAG: + ob, subpos = _loads(fp) + bytes_read += subpos + if returntags: + # Don't interpret the tag, return it and the tagged object. + ob = Tag(aux, ob) + else: + # attempt to interpet the tag and the value into a Python object. + ob = tagify(ob, aux) + return ob, bytes_read + elif tag == CBOR_7: + if tb == CBOR_TRUE: + return (True, bytes_read) + if tb == CBOR_FALSE: + return (False, bytes_read) + if tb == CBOR_NULL: + return (None, bytes_read) + if tb == CBOR_UNDEFINED: + return (None, bytes_read) + raise ValueError("unknown cbor tag 7 byte: {:02x}".format(tb)) + + +def loads_bytes(fp, aux, btag=CBOR_BYTES): + # TODO: limit to some maximum number of chunks and some maximum total bytes + if aux is not None: + # simple case + ob = fp.read(aux) + return (ob, aux) + # read chunks of bytes + chunklist = [] + total_bytes_read = 0 + while True: + tb = fp.read(1)[0] + if not _IS_PY3: + tb = ord(tb) + if tb == CBOR_BREAK: + total_bytes_read += 1 + break + tag, tag_aux, aux, bytes_read = _tag_aux(fp, tb) + assert tag == btag, 'variable length value contains unexpected component' + ob = fp.read(aux) + chunklist.append(ob) + total_bytes_read += bytes_read + aux + return (b''.join(chunklist), total_bytes_read) + + +if _IS_PY3: + def _bytes_to_biguint(bs): + out = 0 + for ch in bs: + out = out << 8 + out = out | ch + return out +else: + def _bytes_to_biguint(bs): + out = 0 + for ch in bs: + out = out << 8 + out = out | ord(ch) + return out + + +def tagify(ob, aux): + # TODO: make this extensible? + # cbor.register_tag_handler(tagnumber, tag_handler) + # where tag_handler takes (tagnumber, tagged_object) + if aux == CBOR_TAG_DATE_STRING: + # TODO: parse RFC3339 date string + pass + if aux == CBOR_TAG_DATE_ARRAY: + return datetime.datetime.utcfromtimestamp(ob) + if aux == CBOR_TAG_BIGNUM: + return _bytes_to_biguint(ob) + if aux == CBOR_TAG_NEGBIGNUM: + return -1 - _bytes_to_biguint(ob) + if aux == CBOR_TAG_REGEX: + # Is this actually a good idea? Should we just return the tag and the raw value to the user somehow? + return re.compile(ob) + return Tag(aux, ob)
--- a/hgext3rd/evolve/utility.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/evolve/utility.py Tue Jan 16 04:35:34 2018 +0100 @@ -5,6 +5,8 @@ # This software may be used and distributed according to the terms of the # GNU General Public License version 2 or any later version. +from mercurial.node import nullrev + shorttemplate = "[{label('evolve.rev', rev)}] {desc|firstline}\n" def obsexcmsg(ui, message, important=False): @@ -20,3 +22,40 @@ if ui.configbool('experimental', 'verbose-obsolescence-exchange', False): topic = 'OBSEXC' ui.progress(topic, *args, **kwargs) + +def filterparents(parents): + """filter nullrev parents + + (and other crazyness)""" + p1, p2 = parents + if p1 == nullrev and p2 == nullrev: + return () + elif p1 != nullrev and (p2 == nullrev or p1 == p2): + return (p1,) + elif p1 == nullrev and p2 != nullrev: + return (p2,) + else: + return parents + +def shouldwarmcache(repo, tr): + configbool = repo.ui.configbool + config = repo.ui.config + desc = getattr(tr, 'desc', '') + + autocase = tr is None or desc.startswith('push') or desc.startswith('serve') + autocache = config('experimental', 'obshashrange.warm-cache', + 'auto') == 'auto' + if autocache: + warm = autocase + else: + # note: we should not get to the default case + warm = configbool('experimental', 'obshashrange.warm-cache', True) + + if not configbool('experimental', 'obshashrange', False): + return False + if not warm: + return False + maxrevs = repo.ui.configint('experimental', 'obshashrange.max-revs', None) + if maxrevs is not None and maxrevs < len(repo.unfiltered()): + return False + return True
--- a/hgext3rd/topic/__init__.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/topic/__init__.py Tue Jan 16 04:35:34 2018 +0100 @@ -127,6 +127,7 @@ registrar, scmutil, templatefilters, + templatekw, util, ) @@ -174,7 +175,7 @@ 'topic.active': 'green', } -__version__ = '0.6.1.dev' +__version__ = '0.7.0' testedwith = '4.1.3 4.2.3 4.3.3 4.4.2' minimumhgversion = '4.1' @@ -325,6 +326,7 @@ cmdutil.summaryhooks.add('topic', summaryhook) + templatekw.keywords['topic'] = topickw # Wrap workingctx extra to return the topic name extensions.wrapfunction(context.workingctx, '__init__', wrapinit) # Wrap changelog.add to drop empty topic @@ -491,6 +493,10 @@ 'topics', 'topic', namemap=_namemap, nodemap=_nodemap, listnames=lambda repo: repo.topics)) +def topickw(**args): + """:topic: String. The topic of the changeset""" + return args['ctx'].topic() + def wrapinit(orig, self, repo, *args, **kwargs): orig(self, repo, *args, **kwargs) if getattr(repo, 'currenttopic', ''): @@ -903,6 +909,9 @@ fm.write('topic', namemask, topic, label=label) fm.data(active=active) + if ui.quiet: + fm.plain('\n') + continue data = stack.stack(repo, topic=topic) fm.plain(' (') if ui.verbose: @@ -1009,16 +1018,7 @@ user = marker.metadata().get('user', user) maxtime = rt - # Making the username more better - username = None - if user: - # user is of form "abc <abc@xyz.com>" - username = user.split('<')[0] - if not username: - # user is of form "<abc@xyz.com>" - username = user[1:-1] - username = username.strip() - + username = stack.parseusername(user) topicuser = (t, username) if trevs:
--- a/hgext3rd/topic/stack.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/topic/stack.py Tue Jan 16 04:35:34 2018 +0100 @@ -28,6 +28,23 @@ if not util.safehasattr(context.basectx, 'isunstable'): context.basectx.isunstable = context.basectx.troubled +def parseusername(user): + """parses the ctx user and returns the username without email ID if + possible, otherwise returns the mail address from that""" + username = None + if user: + # user is of form "abc <abc@xyz.com>" + username = user.split('<')[0] + if not username: + # assuming user is of form "<abc@xyz.com>" + if len(user) > 1: + username = user[1:-1] + else: + username = user + username = username.strip() + + return username + def _stackcandidates(repo): """build the smaller set of revs that might be part of a stack.
--- a/hgext3rd/topic/topicmap.py Sat Dec 16 23:40:39 2017 +0100 +++ b/hgext3rd/topic/topicmap.py Tue Jan 16 04:35:34 2018 +0100 @@ -1,6 +1,7 @@ import contextlib import hashlib +from mercurial.i18n import _ from mercurial.node import nullid from mercurial import ( branchmap, @@ -94,7 +95,23 @@ if ctx.topic() and ctx.branch() == branch: subbranch = "%s:%s" % (branch, ctx.topic()) bheads = repo.branchheads("%s:%s" % (subbranch, ctx.topic())) - return orig(repo, node, branch, bheads=bheads, opts=opts) + + ret = orig(repo, node, branch, bheads=bheads, opts=opts) + + # logic copy-pasted from cmdutil.commitstatus() + if opts is None: + opts = {} + ctx = repo[node] + if ctx.topic(): + return ret + parents = ctx.parents() + + if (not opts.get('amend') and bheads and node not in bheads and not + [x for x in parents if x.node() in bheads and x.branch() == branch]): + repo.ui.status(_("(consider using topic for lightweight branches." + " See 'hg help topic')\n")) + + return ret def _wrapbmcache(ui): class topiccache(_topiccache, branchmap.branchcache):
--- a/tests/test-amend.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-amend.t Tue Jan 16 04:35:34 2018 +0100 @@ -139,7 +139,7 @@ If you don't specify -m, the parent's message will be reused. - If --extra is specified, the behavior of 'hg amend' is reversed: Changes + If --extract is specified, the behavior of 'hg amend' is reversed: Changes to selected files in the checked out revision appear again as uncommitted changed in the working directory.
--- a/tests/test-check-flake8.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-check-flake8.t Tue Jan 16 04:35:34 2018 +0100 @@ -14,5 +14,7 @@ run flake8 if it exists; if it doesn't, then just skip - $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' 2>/dev/null \ + $ hg files -0 'set:(**.py or grep("^#!.*python")) - removed()' \ + > -X hgext3rd/evolve/thirdparty \ + > 2>/dev/null \ > | xargs -0 flake8
--- a/tests/test-discovery-obshashrange.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-discovery-obshashrange.t Tue Jan 16 04:35:34 2018 +0100 @@ -34,9 +34,6 @@ * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugbuilddag .+7 (glob) - * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-depthcache cache reset (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 0o) (glob) * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (8r, 0o) (glob) @@ -79,8 +76,6 @@ * @0000000000000000000000000000000000000000 (*)> log -G exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 (glob) @@ -89,8 +84,6 @@ * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 01241442b3c2bf3211e593b549c655ea65b295e3 --config 'experimental.obshashrange.max-revs=1' exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 (glob) @@ -99,8 +92,6 @@ * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 --config 'experimental.obshashrange.warm-cache=0' exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete (glob) @@ -141,7 +132,11 @@ (run 'hg update' to get a working copy) $ hg -R ../server blackbox * @0000000000000000000000000000000000000000 (*)> debugobshashrange --subranges --rev tip (glob) - * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob) + * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) + * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-depthcache cache reset (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (8r) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 5o) (glob) * @0000000000000000000000000000000000000000 (*)> debugobshashrange --subranges --rev tip exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) @@ -154,10 +149,6 @@ $ rm ../server/.hg/blackbox.log $ hg blackbox * @0000000000000000000000000000000000000000 (*)> pull --rev 4 (glob) - * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-depthcache cache reset (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (5r) (glob) - * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 3o) (glob) * @0000000000000000000000000000000000000000 (*)> updated base branch cache in *.???? seconds (glob) * @0000000000000000000000000000000000000000 (*)> wrote base branch cache with 1 labels and 1 nodes (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (5r, 3o) (glob) @@ -185,7 +176,7 @@ sending hello command sending between command remote: 466 - remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v0 batch branchmap bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Aobsmarkers%3DV0%2CV1%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash + remote: capabilities: _evoext_getbundle_obscommon _evoext_obshash_0 _evoext_obshash_1 _evoext_obshashrange_v1 batch * (glob) remote: 1 preparing listkeys for "phases" sending listkeys command @@ -207,7 +198,7 @@ OBSEXC: looking for common markers in 6 nodes query 0; add more sample (target 100, current 1) query 0; sample size is 9, largest range 5 - sending evoext_obshashrange_v0 command + sending evoext_obshashrange_v1 command obsdiscovery, 0/5 mismatch - 1 obshashrange queries in *.???? seconds (glob) OBSEXC: computing markers relevant to 1 nodes checking for updated bookmarks @@ -238,9 +229,17 @@ received listkey for "phases": 58 bytes $ hg -R ../server blackbox * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) + * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-depthcache cache reset (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (8r) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) - * @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (1r) (glob) + * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-firstmerge cache reset (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-firstmerge in *.???? seconds (9r) (glob) + * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-stablesort cache reset (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-stablesort in *.???? seconds (9r) (glob) * @0000000000000000000000000000000000000000 (*)> obscache is out of date, falling back to slower obsstore version (glob) * @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob) * @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 2 nodes (glob) @@ -279,7 +278,7 @@ [1] $ hg -R ../server blackbox * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) - * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 2o) (glob) * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) @@ -301,8 +300,6 @@ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> add foo (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> add foo exited 0 after *.?? seconds (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> commit -m foo (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 0o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obscache is out of date, falling back to slower obsstore version (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 1 nodes (glob) @@ -310,31 +307,35 @@ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> commit -m foo exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete ffffffffffffffffffffffffffffffffffffffff 45f8b879de922f6a6e620ba04205730335b6fc7e (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete ffffffffffffffffffffffffffffffffffffffff 45f8b879de922f6a6e620ba04205730335b6fc7e exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push -f --debug (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> found 1 common and 1 unknown server heads, 2 roundtrips in *.????s (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (6r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (6r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (6r, 4o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/5 mismatch - 1 obshashrange queries in *.???? seconds (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-firstmerge cache reset (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (6r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-stablesort cache reset (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablesort in *.???? seconds (6r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push -f --debug exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 111111111111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete 22222222222222222bbbbbbbbbbbbb2222222222 2dc09a01254db841290af0538aa52f6f52c776e3 exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/6 mismatch - 1 obshashrange queries in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> push exited 1 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) @@ -384,17 +385,15 @@ * @0000000000000000000000000000000000000000 (*)> -R ../server/ debugobsolete --rev '::tip' exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete aaaaaaa11111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> -R ../server debugobsolete aaaaaaa11111111aaaaaaaaa1111111111111111 66f7d451a68b85ed82ff5fcc254daf50c74144bd exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> debugobsolete bbbbbbb2222222222bbbbbbbbbbbbb2222222222 bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) * @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (glob) - * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob) - * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @0000000000000000000000000000000000000000 (*)> -R ../server debugobsolete bbbbbbb2222222222bbbbbbbbbbbbb2222222222 bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> serve --stdio (glob) + * @0000000000000000000000000000000000000000 (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) + * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @0000000000000000000000000000000000000000 (*)> -R server serve --stdio exited 0 after *.?? seconds (glob) * @0000000000000000000000000000000000000000 (*)> blackbox (glob) $ rm ../server/.hg/blackbox.log @@ -415,10 +414,6 @@ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r 6 (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/6 mismatch - 1 obshashrange queries in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (2r, 3o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 2 nodes (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (2r, 3o) (glob) @@ -492,14 +487,22 @@ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobsolete --rev '::6' exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (2r, 3o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r f69452c5b1af6cbaaa56ef50cf94fff5bcc6ca23 (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 2/7 mismatch - 1 obshashrange queries in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 2o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r f69452c5b1af6cbaaa56ef50cf94fff5bcc6ca23 exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'desc("r3")' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 2 changeset and cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'desc("r3")' exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) $ rm .hg/blackbox.log @@ -516,9 +519,9 @@ 1 new obsolescence markers $ hg blackbox * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r bebd167eb94d257ace0e814aeb98e6972ed2970d (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 1/5 mismatch - 1 obshashrange queries in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull -r bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> blackbox (glob) @@ -558,20 +561,25 @@ repository tip rolled back to revision 7 (undo pull) $ hg blackbox * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache clean - new markers affect 1 changeset and cached ranges (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 2 nodes (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (1r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 1 incoming changes - new heads: 4de32a90b66c (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> rollback (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (2r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablesort in *.???? seconds (2r) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated base branch cache in *.???? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote base branch cache with 1 labels and 2 nodes (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-obscache cache reset (glob) @@ -609,15 +617,9 @@ (run 'hg update' to get a working copy) $ hg blackbox * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-obshashrange cache reset (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 12o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obsdiscovery, 0/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob) - * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (1r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 1 incoming changes - new heads: 4de32a90b66c (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull exited 0 after *.?? seconds (glob) @@ -721,21 +723,27 @@ $ hg blackbox * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> writing .hg/cache/tags2-visible with 0 tags (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (1r) (glob) + * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> debugobshashrange --subranges --rev 'heads(all())' exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> log -G exited 0 after *.?? seconds (glob) * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip -r 'desc("foo")' (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> saved backup bundle to $TESTTMP/client/.hg/strip-backup/45f8b879de92-94c82517-backup.hg (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obscache cache reset (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (5r, 11o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (3r, 0o) (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obshashrange cache reset (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-depthcache cache reset (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-depthcache in *.???? seconds (5r) (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 11o) (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obscache cache reset (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (5r, 11o) (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-depthcache in *.???? seconds (3r) (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated stablerange cache in *.???? seconds (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (3r, 0o) (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (3r, 0o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-stablerange-mergepoint cache reset (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-stablerange-mergepoint in *.???? seconds (8r) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 11o) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-firstmerge cache reset (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-firstmerge in *.???? seconds (8r) (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-stablesort cache reset (glob) + * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-stablesort in *.???? seconds (8r) (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated base branch cache in *.???? seconds (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote base branch cache with 1 labels and 1 nodes (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> 3 incoming changes - new heads: 4de32a90b66c (glob) @@ -745,10 +753,6 @@ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> log -G exited 0 after *.?? seconds (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> pull (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> obsdiscovery, 1/8 mismatch - 1 obshashrange queries in *.???? seconds (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated stablerange cache in *.???? seconds (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> obshashcache reset - new markers affect cached ranges (glob) - * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 2o) (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated base branch cache in *.???? seconds (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote base branch cache with 1 labels and 2 nodes (glob) * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (1r, 2o) (glob)
--- a/tests/test-evolve-list.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-evolve-list.t Tue Jan 16 04:35:34 2018 +0100 @@ -23,7 +23,7 @@ unstable: cb9a9f314b8b (obsolete parent) 177f92b77385: c - orphan: d2ae7f538514 (orphan parent) + unstable: d2ae7f538514 (unstable parent) $ cd ..
--- a/tests/test-evolve-obshistory.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-evolve-obshistory.t Tue Jan 16 04:35:34 2018 +0100 @@ -62,8 +62,9 @@ | x 471f378eab4c (1) A0 rewritten(description, content) as 4ae3a4151de9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/4ae3a4151de9-changeset-description + diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,3 @@ -A0 +A1 @@ -78,13 +79,36 @@ +42 + $ hg obslog --patch --color debug + @ [evolve.node|4ae3a4151de9] [evolve.rev|(3)] [evolve.short_description|A1] + | + x [evolve.node|471f378eab4c] [evolve.rev|(1)] [evolve.short_description|A0] + [evolve.verb|rewritten](description, content) as [evolve.node|4ae3a4151de9] by [evolve.user|test] [evolve.date|(Thu Jan 01 00:00:00 1970 +0000)] + [diff.diffline|diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description] + [diff.file_a|--- a/changeset-description] + [diff.file_b|+++ b/changeset-description] + [diff.hunk|@@ -1,1 +1,3 @@] + [diff.deleted|-A0] + [diff.inserted|+A1] + [diff.inserted|+] + [diff.inserted|+Better commit message] + + [diff.diffline|diff -r 471f378eab4c -r 4ae3a4151de9 A0] + [diff.file_a|--- a/A0 Thu Jan 01 00:00:00 1970 +0000] + [diff.file_b|+++ b/A0 Thu Jan 01 00:00:00 1970 +0000] + [diff.hunk|@@ -1,1 +1,2 @@] + A0 + [diff.inserted|+42] + + $ hg obslog --no-graph --patch 4ae3a4151de9 4ae3a4151de9 (3) A1 471f378eab4c (1) A0 rewritten(description, content) as 4ae3a4151de9 by test (Thu Jan 01 00:00:00 1970 +0000) - --- a/471f378eab4c-changeset-description - +++ b/4ae3a4151de9-changeset-description + diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,3 @@ -A0 +A1 @@ -138,8 +162,9 @@ $ hg obslog --hidden --patch 471f378eab4c x 471f378eab4c (1) A0 rewritten(description, content) as 4ae3a4151de9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/4ae3a4151de9-changeset-description + diff -r 471f378eab4c -r 4ae3a4151de9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,3 @@ -A0 +A1 @@ -826,8 +851,9 @@ $ hg obslog --hidden 471f378eab4c --patch x 471f378eab4c (1) A0 rewritten(description, content) as eb5a0daa2192 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/eb5a0daa2192-changeset-description + diff -r 471f378eab4c -r eb5a0daa2192 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +C0 @@ -849,8 +875,9 @@ | x 471f378eab4c (1) A0 rewritten(description, content) as eb5a0daa2192 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/eb5a0daa2192-changeset-description + diff -r 471f378eab4c -r eb5a0daa2192 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +C0 @@ -879,8 +906,9 @@ | x 471f378eab4c (1) A0 rewritten(description, content) as eb5a0daa2192 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/eb5a0daa2192-changeset-description + diff -r 471f378eab4c -r eb5a0daa2192 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +C0 @@ -903,8 +931,9 @@ | x 471f378eab4c (1) A0 rewritten(description, content) as eb5a0daa2192 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/eb5a0daa2192-changeset-description + diff -r 471f378eab4c -r eb5a0daa2192 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +C0 @@ -979,8 +1008,6 @@ working directory parent is obsolete! (471f378eab4c) (use 'hg evolve' to update to its successor: eb5a0daa2192) $ hg update 0dec01379d3b - working directory parent is obsolete! (471f378eab4c) - (use 'hg evolve' to update to its successor: eb5a0daa2192) abort: hidden revision '0dec01379d3b'! (use --hidden to access hidden revisions; successor: eb5a0daa2192) [255] @@ -1060,15 +1087,17 @@ $ hg obslog --hidden 471f378eab4c --patch x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1083,15 +1112,17 @@ |/ x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1142,15 +1173,17 @@ | x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1165,15 +1198,17 @@ |/ x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1186,15 +1221,17 @@ | x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1208,15 +1245,17 @@ |/ x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1231,15 +1270,17 @@ |/ x 471f378eab4c (1) A0 rewritten(description) as 65b757b745b9 by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/65b757b745b9-changeset-description + diff -r 471f378eab4c -r 65b757b745b9 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A2 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1 @@ -1384,8 +1425,9 @@ |\ x | 471f378eab4c (1) A0 / rewritten(description, content) as eb5a0daa2192 by test (*) (glob) - | --- a/471f378eab4c-changeset-description - | +++ b/eb5a0daa2192-changeset-description + | diff -r 471f378eab4c -r eb5a0daa2192 changeset-description + | --- a/changeset-description + | +++ b/changeset-description | @@ -1,1 +1,1 @@ | -A0 | +C0 @@ -1403,8 +1445,9 @@ | x 0dec01379d3b (2) B0 rewritten(description) as b7ea6d14e664 by test (*) (glob) - --- a/0dec01379d3b-changeset-description - +++ b/b7ea6d14e664-changeset-description + diff -r 0dec01379d3b -r b7ea6d14e664 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -B0 +B1 @@ -1416,8 +1459,9 @@ |\ x | 471f378eab4c (1) A0 / rewritten(description, content) as eb5a0daa2192 by test (*) (glob) - | --- a/471f378eab4c-changeset-description - | +++ b/eb5a0daa2192-changeset-description + | diff -r 471f378eab4c -r eb5a0daa2192 changeset-description + | --- a/changeset-description + | +++ b/changeset-description | @@ -1,1 +1,1 @@ | -A0 | +C0 @@ -1435,8 +1479,9 @@ | x 0dec01379d3b (2) B0 rewritten(description) as b7ea6d14e664 by test (*) (glob) - --- a/0dec01379d3b-changeset-description - +++ b/b7ea6d14e664-changeset-description + diff -r 0dec01379d3b -r b7ea6d14e664 changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -B0 +B1 @@ -1531,12 +1576,8 @@ (use 'hg evolve' to update to its successor: eb5a0daa2192) $ hg update 0dec01379d3b 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory parent is obsolete! (0dec01379d3b) - (use 'hg evolve' to update to its successor: eb5a0daa2192) $ hg update --hidden 'desc(B0)' 0 files updated, 0 files merged, 0 files removed, 0 files unresolved - working directory parent is obsolete! (0dec01379d3b) - (use 'hg evolve' to update to its successor: eb5a0daa2192) Test output with pushed and pulled obs markers ============================================== @@ -1613,8 +1654,9 @@ | x fdf9bde5129a (2) A1 | rewritten(description) as 7a230b46bf61 by test (*) (glob) - | --- a/fdf9bde5129a-changeset-description - | +++ b/7a230b46bf61-changeset-description + | diff -r fdf9bde5129a -r 7a230b46bf61 changeset-description + | --- a/changeset-description + | +++ b/changeset-description | @@ -1,1 +1,1 @@ | -A1 | +A2 @@ -1622,8 +1664,9 @@ | x 471f378eab4c (1) A0 rewritten(description) as fdf9bde5129a by test (*) (glob) - --- a/471f378eab4c-changeset-description - +++ b/fdf9bde5129a-changeset-description + diff -r 471f378eab4c -r fdf9bde5129a changeset-description + --- a/changeset-description + +++ b/changeset-description @@ -1,1 +1,1 @@ -A0 +A1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-evolve-phase.t Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,127 @@ +Testing the handling of phases for `hg evolve` command + + $ cat >> $HGRCPATH <<EOF + > [phases] + > publish = False + > [alias] + > glog = log -G --template='{rev} - {node|short} {desc} ({phase})\n' + > [extensions] + > EOF + $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH + +Testing when there are no conflicts during evolve + + $ hg init noconflict + $ cd noconflict + $ echo a>a + $ hg ci -Aqm a + $ echo b>b + $ hg ci -Aqm b + $ echo c>c + $ hg ci -Aqsm c + $ hg glog + @ 2 - 177f92b77385 c (secret) + | + o 1 - d2ae7f538514 b (draft) + | + o 0 - cb9a9f314b8b a (draft) + + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [1] b + $ echo b2>b + $ hg amend + 1 new unstable changesets + $ hg evolve + move:[2] c + atop:[4] b + working directory is now at 813dde83a7f3 + $ hg glog + @ 5 - 813dde83a7f3 c (secret) + | + o 4 - fd89d0f19529 b (draft) + | + o 0 - cb9a9f314b8b a (draft) + + $ cd .. + +Testing case when there are conflicts (bug 5720) + + $ hg init conflicts + $ cd conflicts + $ echo a > a + $ hg ci -Am a + adding a + $ echo b > a + $ hg ci -m b + $ echo c > a + $ hg ci -sm c + $ hg glog + @ 2 - 13833940840c c (secret) + | + o 1 - 1e6c11564562 b (draft) + | + o 0 - cb9a9f314b8b a (draft) + + + $ hg prev + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + [1] b + $ echo b2 > a + $ hg amend + 1 new unstable changesets + + $ hg glog + @ 4 - 87495ea7c9ec b (draft) + | + | o 2 - 13833940840c c (secret) + | | + | x 1 - 1e6c11564562 b (draft) + |/ + o 0 - cb9a9f314b8b a (draft) + + $ hg evolve + move:[2] c + atop:[4] b + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + + $ hg diff + diff -r 87495ea7c9ec a + --- a/a Thu Jan 01 00:00:00 1970 +0000 + +++ b/a Thu Jan 01 00:00:00 1970 +0000 + @@ -1,1 +1,5 @@ + +<<<<<<< destination: 87495ea7c9ec - test: b + b2 + +======= + +c + +>>>>>>> evolving: 13833940840c - test: c + + $ hg glog + @ 4 - 87495ea7c9ec b (draft) + | + | o 2 - 13833940840c c (secret) + | | + | x 1 - 1e6c11564562 b (draft) + |/ + o 0 - cb9a9f314b8b a (draft) + + + $ echo c2 > a + $ hg resolve -m + (no more unresolved files) + $ hg evolve -c + evolving 2:13833940840c "c" + + $ hg glog + @ 5 - 3d2080c198e5 c (secret) + | + o 4 - 87495ea7c9ec b (draft) + | + o 0 - cb9a9f314b8b a (draft) +
--- a/tests/test-evolve-templates.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-evolve-templates.t Tue Jan 16 04:35:34 2018 +0100 @@ -1130,7 +1130,453 @@ |/ o ea207398892e [] + +Test template with obsmarkers cycle +=================================== +Test setup +---------- + + $ hg init $TESTTMP/templates-local-cycle + $ cd $TESTTMP/templates-local-cycle + $ mkcommit ROOT + $ mkcommit A0 + $ mkcommit B0 + $ hg up -r 0 + 0 files updated, 0 files merged, 2 files removed, 0 files unresolved + $ mkcommit C0 + created new head + +Create the cycle + + $ hg debugobsolete `getid "desc(A0)"` `getid "desc(B0)"` + obsoleted 1 changesets + $ hg debugobsolete `getid "desc(B0)"` `getid "desc(C0)"` + obsoleted 1 changesets + $ hg debugobsolete `getid "desc(B0)"` `getid "desc(A0)"` + +Check templates +--------------- + + $ hg tlog + @ f897c6137566 + | + o ea207398892e + + $ hg fatelog + @ f897c6137566 + | + o ea207398892e + + $ hg up -r "desc(B0)" --hidden + 2 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory parent is obsolete! (0dec01379d3b) + (use 'hg evolve' to update to its parent successor) + $ hg tlog + o f897c6137566 + | Precursors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | @ 0dec01379d3b + | | Precursors: 1:471f378eab4c + | | semi-colon: 1:471f378eab4c + | | Successors: 3:f897c6137566; 1:471f378eab4c + | | semi-colon: 3:f897c6137566; 1:471f378eab4c + | | Fate: rewritten as f897c6137566 + | | Fate: rewritten as 471f378eab4c + | | + | x 471f378eab4c + |/ Precursors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | Successors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | Fate: rewritten as 0dec01379d3b + | + o ea207398892e + + $ hg fatelog + o f897c6137566 + | + | @ 0dec01379d3b + | | Obsfate: rewritten as f897c6137566; rewritten as 471f378eab4c + | | + | x 471f378eab4c + |/ Obsfate: rewritten as 0dec01379d3b + | + o ea207398892e + + $ hg up -r "desc(A0)" --hidden + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + working directory parent is obsolete! (471f378eab4c) + (use 'hg evolve' to update to its parent successor) + $ hg tlog + o f897c6137566 + | Precursors: 1:471f378eab4c + | semi-colon: 1:471f378eab4c + | @ 471f378eab4c + |/ Fate: pruned + | + o ea207398892e + + $ hg fatelog + o f897c6137566 + | + | @ 471f378eab4c + |/ Obsfate: pruned + | + o ea207398892e + + + $ hg up -r "desc(ROOT)" --hidden + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg tlog + o f897c6137566 + | + @ ea207398892e + + $ hg fatelog + o f897c6137566 + | + @ ea207398892e + + $ hg tlog --hidden + o f897c6137566 + | Precursors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | x 0dec01379d3b + | | Precursors: 1:471f378eab4c + | | semi-colon: 1:471f378eab4c + | | Successors: 3:f897c6137566; 1:471f378eab4c + | | semi-colon: 3:f897c6137566; 1:471f378eab4c + | | Fate: rewritten as f897c6137566 + | | Fate: rewritten as 471f378eab4c + | | + | x 471f378eab4c + |/ Precursors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | Successors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | Fate: rewritten as 0dec01379d3b + | + @ ea207398892e + +Test template with split + divergence with cycles +================================================= + + $ hg log -G + o changeset: 3:f897c6137566 + | tag: tip + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + @ changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ hg up + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + +Create a commit with three files + $ touch A B C + $ hg commit -A -m "Add A,B,C" A B C + +Split it + $ hg up 3 + 0 files updated, 0 files merged, 3 files removed, 0 files unresolved + $ touch A + $ hg commit -A -m "Add A,B,C" A + created new head + + $ touch B + $ hg commit -A -m "Add A,B,C" B + + $ touch C + $ hg commit -A -m "Add A,B,C" C + + $ hg log -G + @ changeset: 7:ba2ed02b0c9a + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + o changeset: 6:4a004186e638 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + o changeset: 5:dd800401bd8c + | parent: 3:f897c6137566 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + | o changeset: 4:9bd10a0775e4 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + o changeset: 3:f897c6137566 + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + + $ hg debugobsolete `getid "4"` `getid "5"` `getid "6"` `getid "7"` + obsoleted 1 changesets + $ hg log -G + @ changeset: 7:ba2ed02b0c9a + | tag: tip + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + o changeset: 6:4a004186e638 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + o changeset: 5:dd800401bd8c + | parent: 3:f897c6137566 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: Add A,B,C + | + o changeset: 3:f897c6137566 + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Diverge one of the splitted commit + + $ hg up 6 + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + $ hg commit --amend -m "Add only B" + 1 new unstable changesets + + $ hg up 6 --hidden + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (4a004186e638) + (use 'hg evolve' to update to its successor: b18bc8331526) + $ hg commit --amend -m "Add B only" + 4 new divergent changesets + + $ hg log -G + @ changeset: 9:0b997eb7ceee + | tag: tip + | parent: 5:dd800401bd8c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: divergent + | summary: Add B only + | + | o changeset: 8:b18bc8331526 + |/ parent: 5:dd800401bd8c + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: divergent + | summary: Add only B + | + | o changeset: 7:ba2ed02b0c9a + | | user: test + | | date: Thu Jan 01 00:00:00 1970 +0000 + | | trouble: unstable, divergent + | | summary: Add A,B,C + | | + | x changeset: 6:4a004186e638 + |/ user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | obsolete: reworded as b18bc8331526 + | obsolete: reworded as 0b997eb7ceee + | summary: Add A,B,C + | + o changeset: 5:dd800401bd8c + | parent: 3:f897c6137566 + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | trouble: divergent + | summary: Add A,B,C + | + o changeset: 3:f897c6137566 + | parent: 0:ea207398892e + | user: test + | date: Thu Jan 01 00:00:00 1970 +0000 + | summary: C0 + | + o changeset: 0:ea207398892e + user: test + date: Thu Jan 01 00:00:00 1970 +0000 + summary: ROOT + +Check templates +--------------- + + $ hg tlog + @ 0b997eb7ceee + | Precursors: 6:4a004186e638 + | semi-colon: 6:4a004186e638 + | o b18bc8331526 + |/ Precursors: 6:4a004186e638 + | semi-colon: 6:4a004186e638 + | o ba2ed02b0c9a + | | + | x 4a004186e638 + |/ Successors: 8:b18bc8331526; 9:0b997eb7ceee + | semi-colon: 8:b18bc8331526; 9:0b997eb7ceee + | Fate: reworded as b18bc8331526 + | Fate: reworded as 0b997eb7ceee + | + o dd800401bd8c + | + o f897c6137566 + | + o ea207398892e + + $ hg fatelog + @ 0b997eb7ceee + | + | o b18bc8331526 + |/ + | o ba2ed02b0c9a + | | + | x 4a004186e638 + |/ Obsfate: reworded as b18bc8331526; reworded as 0b997eb7ceee + | + o dd800401bd8c + | + o f897c6137566 + | + o ea207398892e + + $ hg tlog --hidden + @ 0b997eb7ceee + | Precursors: 6:4a004186e638 + | semi-colon: 6:4a004186e638 + | o b18bc8331526 + |/ Precursors: 6:4a004186e638 + | semi-colon: 6:4a004186e638 + | o ba2ed02b0c9a + | | Precursors: 4:9bd10a0775e4 + | | semi-colon: 4:9bd10a0775e4 + | x 4a004186e638 + |/ Precursors: 4:9bd10a0775e4 + | semi-colon: 4:9bd10a0775e4 + | Successors: 8:b18bc8331526; 9:0b997eb7ceee + | semi-colon: 8:b18bc8331526; 9:0b997eb7ceee + | Fate: reworded as b18bc8331526 + | Fate: reworded as 0b997eb7ceee + | + o dd800401bd8c + | Precursors: 4:9bd10a0775e4 + | semi-colon: 4:9bd10a0775e4 + | x 9bd10a0775e4 + |/ Successors: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a + | semi-colon: 5:dd800401bd8c 6:4a004186e638 7:ba2ed02b0c9a + | Fate: split as 4a004186e638, ba2ed02b0c9a, dd800401bd8c + | + o f897c6137566 + | Precursors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | x 0dec01379d3b + | | Precursors: 1:471f378eab4c + | | semi-colon: 1:471f378eab4c + | | Successors: 3:f897c6137566; 1:471f378eab4c + | | semi-colon: 3:f897c6137566; 1:471f378eab4c + | | Fate: rewritten as f897c6137566 + | | Fate: rewritten as 471f378eab4c + | | + | x 471f378eab4c + |/ Precursors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | Successors: 2:0dec01379d3b + | semi-colon: 2:0dec01379d3b + | Fate: rewritten as 0dec01379d3b + | + o ea207398892e + + $ hg fatelog --hidden + @ 0b997eb7ceee + | + | o b18bc8331526 + |/ + | o ba2ed02b0c9a + | | + | x 4a004186e638 + |/ Obsfate: reworded as b18bc8331526; reworded as 0b997eb7ceee + | + o dd800401bd8c + | + | x 9bd10a0775e4 + |/ Obsfate: split as 4a004186e638, ba2ed02b0c9a, dd800401bd8c + | + o f897c6137566 + | + | x 0dec01379d3b + | | Obsfate: rewritten as f897c6137566; rewritten as 471f378eab4c + | | + | x 471f378eab4c + |/ Obsfate: rewritten as 0dec01379d3b + | + o ea207398892e + + $ hg up --hidden 4 + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + working directory parent is obsolete! (9bd10a0775e4) + (9bd10a0775e4 has diverged, use 'hg evolve --list --content-divergent' to resolve the issue) + $ hg rebase -r 7 -d 8 --config extensions.rebase= + rebasing 7:ba2ed02b0c9a "Add A,B,C" + $ hg tlog + o eceed8f98ffc + | Precursors: 4:9bd10a0775e4 + | semi-colon: 4:9bd10a0775e4 + | o 0b997eb7ceee + | | Precursors: 4:9bd10a0775e4 + | | semi-colon: 4:9bd10a0775e4 + o | b18bc8331526 + |/ Precursors: 4:9bd10a0775e4 + | semi-colon: 4:9bd10a0775e4 + o dd800401bd8c + | Precursors: 4:9bd10a0775e4 + | semi-colon: 4:9bd10a0775e4 + | @ 9bd10a0775e4 + |/ Successors: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc; 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc + | semi-colon: 5:dd800401bd8c 9:0b997eb7ceee 10:eceed8f98ffc; 5:dd800401bd8c 8:b18bc8331526 10:eceed8f98ffc + | Fate: split as 0b997eb7ceee, dd800401bd8c, eceed8f98ffc + | Fate: split as b18bc8331526, dd800401bd8c, eceed8f98ffc + | + o f897c6137566 + | + o ea207398892e + + $ hg fatelog + o eceed8f98ffc + | + | o 0b997eb7ceee + | | + o | b18bc8331526 + |/ + o dd800401bd8c + | + | @ 9bd10a0775e4 + |/ Obsfate: split as 0b997eb7ceee, dd800401bd8c, eceed8f98ffc; split as b18bc8331526, dd800401bd8c, eceed8f98ffc + | + o f897c6137566 + | + o ea207398892e + Test templates with pruned commits ==================================
--- a/tests/test-evolve-topic.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-evolve-topic.t Tue Jan 16 04:35:34 2018 +0100 @@ -224,3 +224,46 @@ switching to topic foo 0 files updated, 0 files merged, 1 files removed, 0 files unresolved [14] add eee + +Testing when instability is involved + + $ hg log -G + o 19 - {bar} 9bf430c106b7 add jjj (draft) + | + o 18 - {bar} d2dc89c57700 add iii (draft) + | + o 17 - {bar} 20bc4d02aa62 add hhh (draft) + | + o 16 - {bar} 16d6f664b17c add ggg (draft) + | + o 15 - {foo} 070c5573d8f9 add fff (draft) + | + @ 14 - {foo} 42b49017ff90 add eee (draft) + | + o 11 - {foo} d9cacd156ffc add ddd (draft) + | + o 2 - {foo} cced9bac76e3 add ccc (draft) + | + o 1 - {} a4dbed0837ea add bbb (draft) + | + o 0 - {} 199cc73e9a0b add aaa (draft) + + $ hg topic -r 070c5573d8f9 bar + changed topic on 1 changes + $ hg up 16d6f664b17c + switching to topic bar + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg stack + ### topic: bar + ### target: default (branch) + t5$ add jjj (unstable) + t4$ add iii (unstable) + t3$ add hhh (unstable) + t2$ add ggg (current unstable) + t1: add fff + t0^ add eee (base) + + $ hg prev + 0 files updated, 0 files merged, 1 files removed, 0 files unresolved + [20] add fff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-issue-5720.t Tue Jan 16 04:35:34 2018 +0100 @@ -0,0 +1,87 @@ +This test file test the #5720 issue + +Check that `hg evolve --continue` doesn't change changeset phase from secret +to draft after a merge conflict. + +https://bz.mercurial-scm.org/show_bug.cgi?id=5720 + +Global setup +============ + + $ . $TESTDIR/testlib/common.sh + $ cat >> $HGRCPATH <<EOF + > [ui] + > interactive = true + > [phases] + > publish=False + > [extensions] + > evolve = + > EOF + +Test +==== + + $ hg init $TESTTMP/issue-5720 + $ cd $TESTTMP/issue-5720 + +Create two drafts commits and one secret + $ echo a > a + $ hg commit -Am a + adding a + $ echo b > a + $ hg commit -m b + $ echo c > a + $ hg commit --secret -m c + $ hg log -G -T "{rev}: {phase}" + @ 2: secret + | + o 1: draft + | + o 0: draft + +Amend the second draft with new content + $ hg prev + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + [1] b + $ echo b2 > a + $ hg amend + 1 new unstable changesets + $ hg log -G -T "{rev}: {phase}" + @ 4: draft + | + | o 2: secret + | | + | x 1: draft + |/ + o 0: draft + +Evolve which triggers a conflict + $ hg evolve + move:[2] c + atop:[4] b + merging a + warning: conflicts while merging a! (edit, then use 'hg resolve --mark') + evolve failed! + fix conflict and run 'hg evolve --continue' or use 'hg update -C .' to abort + abort: unresolved merge conflicts (see hg help resolve) + [255] + +Fix the conflict + $ echo c2 > a + $ hg resolve -m + (no more unresolved files) + +Continue the evolution + $ hg evolve --continue + evolving 2:13833940840c "c" + +Tip should stay in secret phase + $ hg log -G -T "{rev}: {phase}" + @ 5: secret + | + o 4: draft + | + o 0: draft + + $ hg log -r . -T '{phase}\n' + secret
--- a/tests/test-minitopic.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-minitopic.t Tue Jan 16 04:35:34 2018 +0100 @@ -81,6 +81,7 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ mkcommit c_C0 created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg push enabled pushing to http://localhost:$HGPORT/ searching for changes
--- a/tests/test-stabilize-conflict.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-stabilize-conflict.t Tue Jan 16 04:35:34 2018 +0100 @@ -168,7 +168,7 @@ $ hg resolve --all -m (no more unresolved files) $ hg evolve --continue - grafting 5:71c18f70c34f "babar count up to fifteen" + evolving 5:71c18f70c34f "babar count up to fifteen" $ hg resolve -l $ hg log -G @ changeset: 8:1836b91c6c1d
--- a/tests/test-stabilize-result.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-stabilize-result.t Tue Jan 16 04:35:34 2018 +0100 @@ -96,13 +96,13 @@ +a +newer a $ hg evolve --continue - grafting 5:3655f0f50885 "newer a" + evolving 5:3655f0f50885 "newer a" abort: unresolved merge conflicts (see 'hg help resolve') [255] $ hg resolve -m a (no more unresolved files) $ hg evolve --continue - grafting 5:3655f0f50885 "newer a" + evolving 5:3655f0f50885 "newer a" Stabilize latecomer with different parent ========================================= @@ -162,7 +162,7 @@ hg rebase --rev (73b15c7566e9|d5c7ef82d003) --dest 66719795a494; (re) hg update 1cf0aacfd363; hg revert --all --rev (73b15c7566e9|d5c7ef82d003); (re) - hg commit --msg "bumped update to %s" (no-eol) + hg commit --msg "bumped update to d5c7ef82d003" $ hg evolve --any --confirm --phase-divergent recreate:[12] newer a atop:[8] newer a
--- a/tests/test-stablerange.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-stablerange.t Tue Jan 16 04:35:34 2018 +0100 @@ -9,7 +9,7 @@ > [ui] > logtemplate = "{rev} {node|short} {desc} {tags}\n" > [defaults] - > debugstablerange = --method mergepoint + > debugstablerange = --method default > EOF Simple linear test @@ -449,14 +449,14 @@ We are still able to reuse one of the branch however $ hg debugstablerange --verify --verbose --subranges --rev merge - 8aca7f8c9bd2-0 (10, 11, 11) [complete] - bebd167eb94d-0 (4, 5, 5), 42b07e8da27d-1 (7, 4, 3), 8aca7f8c9bd2-8 (10, 11, 3) - bebd167eb94d-0 (4, 5, 5) [complete] - 2dc09a01254d-0 (3, 4, 4), bebd167eb94d-4 (4, 5, 1) - 2dc09a01254d-0 (3, 4, 4) [complete] - 66f7d451a68b-0 (1, 2, 2), 2dc09a01254d-2 (3, 4, 2) - 42b07e8da27d-1 (7, 4, 3) [complete] - de561312eff4-1 (5, 2, 1), 42b07e8da27d-2 (7, 4, 2) - 8aca7f8c9bd2-8 (10, 11, 3) [complete] - f4b7da68b467-4 (9, 6, 2), 8aca7f8c9bd2-10 (10, 11, 1) - 2dc09a01254d-2 (3, 4, 2) [complete] - 01241442b3c2-2 (2, 3, 1), 2dc09a01254d-3 (3, 4, 1) + 8aca7f8c9bd2-0 (10, 11, 11) [complete] - f4b7da68b467-0 (9, 6, 6), 01241442b3c2-1 (2, 3, 2), 8aca7f8c9bd2-8 (10, 11, 3) + f4b7da68b467-0 (9, 6, 6) [complete] - 42b07e8da27d-0 (7, 4, 4), f4b7da68b467-4 (9, 6, 2) + 42b07e8da27d-0 (7, 4, 4) [complete] - de561312eff4-0 (5, 2, 2), 42b07e8da27d-2 (7, 4, 2) + 8aca7f8c9bd2-8 (10, 11, 3) [complete] - bebd167eb94d-3 (4, 5, 2), 8aca7f8c9bd2-10 (10, 11, 1) + 01241442b3c2-1 (2, 3, 2) [complete] - 66f7d451a68b-1 (1, 2, 1), 01241442b3c2-2 (2, 3, 1) 42b07e8da27d-2 (7, 4, 2) [complete] - b9bc20507e0b-2 (6, 3, 1), 42b07e8da27d-3 (7, 4, 1) - 66f7d451a68b-0 (1, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), 66f7d451a68b-1 (1, 2, 1) + bebd167eb94d-3 (4, 5, 2) [complete] - 2dc09a01254d-3 (3, 4, 1), bebd167eb94d-4 (4, 5, 1) + de561312eff4-0 (5, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), de561312eff4-1 (5, 2, 1) f4b7da68b467-4 (9, 6, 2) [complete] - 857477a9aebb-4 (8, 5, 1), f4b7da68b467-5 (9, 6, 1) 01241442b3c2-2 (2, 3, 1) [leaf] - 1ea73414a91b-0 (0, 1, 1) [leaf] - @@ -474,14 +474,18 @@ --- left.range * (glob) +++ merge.range * (glob) @@ -1,9 +1,20 @@ - +8aca7f8c9bd2-0 (10, 11, 11) [complete] - bebd167eb94d-0 (4, 5, 5), 42b07e8da27d-1 (7, 4, 3), 8aca7f8c9bd2-8 (10, 11, 3) - bebd167eb94d-0 (4, 5, 5) [complete] - 2dc09a01254d-0 (3, 4, 4), bebd167eb94d-4 (4, 5, 1) - 2dc09a01254d-0 (3, 4, 4) [complete] - 66f7d451a68b-0 (1, 2, 2), 2dc09a01254d-2 (3, 4, 2) - +42b07e8da27d-1 (7, 4, 3) [complete] - de561312eff4-1 (5, 2, 1), 42b07e8da27d-2 (7, 4, 2) - +8aca7f8c9bd2-8 (10, 11, 3) [complete] - f4b7da68b467-4 (9, 6, 2), 8aca7f8c9bd2-10 (10, 11, 1) - 2dc09a01254d-2 (3, 4, 2) [complete] - 01241442b3c2-2 (2, 3, 1), 2dc09a01254d-3 (3, 4, 1) + -bebd167eb94d-0 (4, 5, 5) [complete] - 2dc09a01254d-0 (3, 4, 4), bebd167eb94d-4 (4, 5, 1) + -2dc09a01254d-0 (3, 4, 4) [complete] - 66f7d451a68b-0 (1, 2, 2), 2dc09a01254d-2 (3, 4, 2) + -2dc09a01254d-2 (3, 4, 2) [complete] - 01241442b3c2-2 (2, 3, 1), 2dc09a01254d-3 (3, 4, 1) + -66f7d451a68b-0 (1, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), 66f7d451a68b-1 (1, 2, 1) + +8aca7f8c9bd2-0 (10, 11, 11) [complete] - f4b7da68b467-0 (9, 6, 6), 01241442b3c2-1 (2, 3, 2), 8aca7f8c9bd2-8 (10, 11, 3) + +f4b7da68b467-0 (9, 6, 6) [complete] - 42b07e8da27d-0 (7, 4, 4), f4b7da68b467-4 (9, 6, 2) + +42b07e8da27d-0 (7, 4, 4) [complete] - de561312eff4-0 (5, 2, 2), 42b07e8da27d-2 (7, 4, 2) + +8aca7f8c9bd2-8 (10, 11, 3) [complete] - bebd167eb94d-3 (4, 5, 2), 8aca7f8c9bd2-10 (10, 11, 1) + +01241442b3c2-1 (2, 3, 2) [complete] - 66f7d451a68b-1 (1, 2, 1), 01241442b3c2-2 (2, 3, 1) +42b07e8da27d-2 (7, 4, 2) [complete] - b9bc20507e0b-2 (6, 3, 1), 42b07e8da27d-3 (7, 4, 1) - 66f7d451a68b-0 (1, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), 66f7d451a68b-1 (1, 2, 1) + +bebd167eb94d-3 (4, 5, 2) [complete] - 2dc09a01254d-3 (3, 4, 1), bebd167eb94d-4 (4, 5, 1) + +de561312eff4-0 (5, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), de561312eff4-1 (5, 2, 1) +f4b7da68b467-4 (9, 6, 2) [complete] - 857477a9aebb-4 (8, 5, 1), f4b7da68b467-5 (9, 6, 1) 01241442b3c2-2 (2, 3, 1) [leaf] - 1ea73414a91b-0 (0, 1, 1) [leaf] - @@ -499,17 +503,14 @@ --- right.range * (glob) +++ merge.range * (glob) @@ -1,11 +1,20 @@ - -f4b7da68b467-0 (9, 6, 6) [complete] - 42b07e8da27d-0 (7, 4, 4), f4b7da68b467-4 (9, 6, 2) - -42b07e8da27d-0 (7, 4, 4) [complete] - de561312eff4-0 (5, 2, 2), 42b07e8da27d-2 (7, 4, 2) - +8aca7f8c9bd2-0 (10, 11, 11) [complete] - bebd167eb94d-0 (4, 5, 5), 42b07e8da27d-1 (7, 4, 3), 8aca7f8c9bd2-8 (10, 11, 3) - +bebd167eb94d-0 (4, 5, 5) [complete] - 2dc09a01254d-0 (3, 4, 4), bebd167eb94d-4 (4, 5, 1) - +2dc09a01254d-0 (3, 4, 4) [complete] - 66f7d451a68b-0 (1, 2, 2), 2dc09a01254d-2 (3, 4, 2) - +42b07e8da27d-1 (7, 4, 3) [complete] - de561312eff4-1 (5, 2, 1), 42b07e8da27d-2 (7, 4, 2) - +8aca7f8c9bd2-8 (10, 11, 3) [complete] - f4b7da68b467-4 (9, 6, 2), 8aca7f8c9bd2-10 (10, 11, 1) - +2dc09a01254d-2 (3, 4, 2) [complete] - 01241442b3c2-2 (2, 3, 1), 2dc09a01254d-3 (3, 4, 1) + +8aca7f8c9bd2-0 (10, 11, 11) [complete] - f4b7da68b467-0 (9, 6, 6), 01241442b3c2-1 (2, 3, 2), 8aca7f8c9bd2-8 (10, 11, 3) + f4b7da68b467-0 (9, 6, 6) [complete] - 42b07e8da27d-0 (7, 4, 4), f4b7da68b467-4 (9, 6, 2) + 42b07e8da27d-0 (7, 4, 4) [complete] - de561312eff4-0 (5, 2, 2), 42b07e8da27d-2 (7, 4, 2) + +8aca7f8c9bd2-8 (10, 11, 3) [complete] - bebd167eb94d-3 (4, 5, 2), 8aca7f8c9bd2-10 (10, 11, 1) + +01241442b3c2-1 (2, 3, 2) [complete] - 66f7d451a68b-1 (1, 2, 1), 01241442b3c2-2 (2, 3, 1) 42b07e8da27d-2 (7, 4, 2) [complete] - b9bc20507e0b-2 (6, 3, 1), 42b07e8da27d-3 (7, 4, 1) - -de561312eff4-0 (5, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), de561312eff4-1 (5, 2, 1) - +66f7d451a68b-0 (1, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), 66f7d451a68b-1 (1, 2, 1) + +bebd167eb94d-3 (4, 5, 2) [complete] - 2dc09a01254d-3 (3, 4, 1), bebd167eb94d-4 (4, 5, 1) + de561312eff4-0 (5, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), de561312eff4-1 (5, 2, 1) f4b7da68b467-4 (9, 6, 2) [complete] - 857477a9aebb-4 (8, 5, 1), f4b7da68b467-5 (9, 6, 1) +01241442b3c2-2 (2, 3, 1) [leaf] - 1ea73414a91b-0 (0, 1, 1) [leaf] - @@ -527,16 +528,16 @@ Range above the merge, reuse subrange from the merge $ hg debugstablerange --verify --verbose --subranges --rev tip - e6b8d5b46647-0 (12, 13, 13) [complete] - bebd167eb94d-0 (4, 5, 5), 42b07e8da27d-1 (7, 4, 3), e6b8d5b46647-8 (12, 13, 5) - bebd167eb94d-0 (4, 5, 5) [complete] - 2dc09a01254d-0 (3, 4, 4), bebd167eb94d-4 (4, 5, 1) + e6b8d5b46647-0 (12, 13, 13) [complete] - f4b7da68b467-0 (9, 6, 6), 01241442b3c2-1 (2, 3, 2), e6b8d5b46647-8 (12, 13, 5) + f4b7da68b467-0 (9, 6, 6) [complete] - 42b07e8da27d-0 (7, 4, 4), f4b7da68b467-4 (9, 6, 2) e6b8d5b46647-8 (12, 13, 5) [complete] - 485383494a89-8 (11, 12, 4), e6b8d5b46647-12 (12, 13, 1) - 2dc09a01254d-0 (3, 4, 4) [complete] - 66f7d451a68b-0 (1, 2, 2), 2dc09a01254d-2 (3, 4, 2) - 485383494a89-8 (11, 12, 4) [complete] - f4b7da68b467-4 (9, 6, 2), 485383494a89-10 (11, 12, 2) - 42b07e8da27d-1 (7, 4, 3) [complete] - de561312eff4-1 (5, 2, 1), 42b07e8da27d-2 (7, 4, 2) - 2dc09a01254d-2 (3, 4, 2) [complete] - 01241442b3c2-2 (2, 3, 1), 2dc09a01254d-3 (3, 4, 1) + 42b07e8da27d-0 (7, 4, 4) [complete] - de561312eff4-0 (5, 2, 2), 42b07e8da27d-2 (7, 4, 2) + 485383494a89-8 (11, 12, 4) [complete] - bebd167eb94d-3 (4, 5, 2), 485383494a89-10 (11, 12, 2) + 01241442b3c2-1 (2, 3, 2) [complete] - 66f7d451a68b-1 (1, 2, 1), 01241442b3c2-2 (2, 3, 1) 42b07e8da27d-2 (7, 4, 2) [complete] - b9bc20507e0b-2 (6, 3, 1), 42b07e8da27d-3 (7, 4, 1) 485383494a89-10 (11, 12, 2) [complete] - 8aca7f8c9bd2-10 (10, 11, 1), 485383494a89-11 (11, 12, 1) - 66f7d451a68b-0 (1, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), 66f7d451a68b-1 (1, 2, 1) + bebd167eb94d-3 (4, 5, 2) [complete] - 2dc09a01254d-3 (3, 4, 1), bebd167eb94d-4 (4, 5, 1) + de561312eff4-0 (5, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), de561312eff4-1 (5, 2, 1) f4b7da68b467-4 (9, 6, 2) [complete] - 857477a9aebb-4 (8, 5, 1), f4b7da68b467-5 (9, 6, 1) 01241442b3c2-2 (2, 3, 1) [leaf] - 1ea73414a91b-0 (0, 1, 1) [leaf] - @@ -555,21 +556,21 @@ $ diff -u merge.range tip.range --- merge.range * (glob) +++ tip.range * (glob) - @@ -1,20 +1,24 @@ - -8aca7f8c9bd2-0 (10, 11, 11) [complete] - bebd167eb94d-0 (4, 5, 5), 42b07e8da27d-1 (7, 4, 3), 8aca7f8c9bd2-8 (10, 11, 3) - +e6b8d5b46647-0 (12, 13, 13) [complete] - bebd167eb94d-0 (4, 5, 5), 42b07e8da27d-1 (7, 4, 3), e6b8d5b46647-8 (12, 13, 5) - bebd167eb94d-0 (4, 5, 5) [complete] - 2dc09a01254d-0 (3, 4, 4), bebd167eb94d-4 (4, 5, 1) + @@ -1,9 +1,11 @@ + -8aca7f8c9bd2-0 (10, 11, 11) [complete] - f4b7da68b467-0 (9, 6, 6), 01241442b3c2-1 (2, 3, 2), 8aca7f8c9bd2-8 (10, 11, 3) + +e6b8d5b46647-0 (12, 13, 13) [complete] - f4b7da68b467-0 (9, 6, 6), 01241442b3c2-1 (2, 3, 2), e6b8d5b46647-8 (12, 13, 5) + f4b7da68b467-0 (9, 6, 6) [complete] - 42b07e8da27d-0 (7, 4, 4), f4b7da68b467-4 (9, 6, 2) +e6b8d5b46647-8 (12, 13, 5) [complete] - 485383494a89-8 (11, 12, 4), e6b8d5b46647-12 (12, 13, 1) - 2dc09a01254d-0 (3, 4, 4) [complete] - 66f7d451a68b-0 (1, 2, 2), 2dc09a01254d-2 (3, 4, 2) - +485383494a89-8 (11, 12, 4) [complete] - f4b7da68b467-4 (9, 6, 2), 485383494a89-10 (11, 12, 2) - 42b07e8da27d-1 (7, 4, 3) [complete] - de561312eff4-1 (5, 2, 1), 42b07e8da27d-2 (7, 4, 2) - -8aca7f8c9bd2-8 (10, 11, 3) [complete] - f4b7da68b467-4 (9, 6, 2), 8aca7f8c9bd2-10 (10, 11, 1) - 2dc09a01254d-2 (3, 4, 2) [complete] - 01241442b3c2-2 (2, 3, 1), 2dc09a01254d-3 (3, 4, 1) + 42b07e8da27d-0 (7, 4, 4) [complete] - de561312eff4-0 (5, 2, 2), 42b07e8da27d-2 (7, 4, 2) + -8aca7f8c9bd2-8 (10, 11, 3) [complete] - bebd167eb94d-3 (4, 5, 2), 8aca7f8c9bd2-10 (10, 11, 1) + +485383494a89-8 (11, 12, 4) [complete] - bebd167eb94d-3 (4, 5, 2), 485383494a89-10 (11, 12, 2) + 01241442b3c2-1 (2, 3, 2) [complete] - 66f7d451a68b-1 (1, 2, 1), 01241442b3c2-2 (2, 3, 1) 42b07e8da27d-2 (7, 4, 2) [complete] - b9bc20507e0b-2 (6, 3, 1), 42b07e8da27d-3 (7, 4, 1) +485383494a89-10 (11, 12, 2) [complete] - 8aca7f8c9bd2-10 (10, 11, 1), 485383494a89-11 (11, 12, 1) - 66f7d451a68b-0 (1, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), 66f7d451a68b-1 (1, 2, 1) + bebd167eb94d-3 (4, 5, 2) [complete] - 2dc09a01254d-3 (3, 4, 1), bebd167eb94d-4 (4, 5, 1) + de561312eff4-0 (5, 2, 2) [complete] - 1ea73414a91b-0 (0, 1, 1), de561312eff4-1 (5, 2, 1) f4b7da68b467-4 (9, 6, 2) [complete] - 857477a9aebb-4 (8, 5, 1), f4b7da68b467-5 (9, 6, 1) - 01241442b3c2-2 (2, 3, 1) [leaf] - + @@ -11,10 +13,12 @@ 1ea73414a91b-0 (0, 1, 1) [leaf] - 2dc09a01254d-3 (3, 4, 1) [leaf] - 42b07e8da27d-3 (7, 4, 1) [leaf] -
--- a/tests/test-stablesort-criss-cross.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-stablesort-criss-cross.t Tue Jan 16 04:35:34 2018 +0100 @@ -9,7 +9,7 @@ > [ui] > logtemplate = "{rev} {node|short} {desc} {tags}\n" > [alias] - > showsort = debugstablesort --template="{node|short}\n" --method headcached + > showsort = debugstablesort --template="{node|short}\n" --method headondisk > EOF $ checktopo () { @@ -397,11 +397,11 @@ 1ea73414a91b 66f7d451a68b 01241442b3c2 - 0c1445abb33d - 65eb34ffc3a8 2dc09a01254d bebd167eb94d c8d03c1b5e94 + 0c1445abb33d + 65eb34ffc3a8 07c648efceeb c81423bf5a24 5ba9a53052ed @@ -409,11 +409,11 @@ === checking 1ea73414a91b === === checking 66f7d451a68b === === checking 01241442b3c2 === - === checking 0c1445abb33d === - === checking 65eb34ffc3a8 === === checking 2dc09a01254d === === checking bebd167eb94d === === checking c8d03c1b5e94 === + === checking 0c1445abb33d === + === checking 65eb34ffc3a8 === === checking 07c648efceeb === === checking c81423bf5a24 === === checking 5ba9a53052ed === @@ -421,41 +421,41 @@ 1ea73414a91b 66f7d451a68b 01241442b3c2 - 0c1445abb33d - 65eb34ffc3a8 2dc09a01254d bebd167eb94d c8d03c1b5e94 + 0c1445abb33d + 65eb34ffc3a8 c81423bf5a24 $ checktopo AmergeA === checking 1ea73414a91b === === checking 66f7d451a68b === === checking 01241442b3c2 === - === checking 0c1445abb33d === - === checking 65eb34ffc3a8 === === checking 2dc09a01254d === === checking bebd167eb94d === === checking c8d03c1b5e94 === + === checking 0c1445abb33d === + === checking 65eb34ffc3a8 === === checking c81423bf5a24 === $ hg showsort --rev 'AmergeB' 1ea73414a91b 66f7d451a68b 01241442b3c2 - 0c1445abb33d - 65eb34ffc3a8 2dc09a01254d bebd167eb94d c8d03c1b5e94 + 0c1445abb33d + 65eb34ffc3a8 07c648efceeb $ checktopo AmergeB === checking 1ea73414a91b === === checking 66f7d451a68b === === checking 01241442b3c2 === - === checking 0c1445abb33d === - === checking 65eb34ffc3a8 === === checking 2dc09a01254d === === checking bebd167eb94d === === checking c8d03c1b5e94 === + === checking 0c1445abb33d === + === checking 65eb34ffc3a8 === === checking 07c648efceeb === close criss cross @@ -463,11 +463,11 @@ 1ea73414a91b 66f7d451a68b 01241442b3c2 - 0c1445abb33d - 65eb34ffc3a8 2dc09a01254d bebd167eb94d c8d03c1b5e94 + 0c1445abb33d + 65eb34ffc3a8 07c648efceeb c81423bf5a24 5ba9a53052ed @@ -481,11 +481,11 @@ === checking 1ea73414a91b === === checking 66f7d451a68b === === checking 01241442b3c2 === - === checking 0c1445abb33d === - === checking 65eb34ffc3a8 === === checking 2dc09a01254d === === checking bebd167eb94d === === checking c8d03c1b5e94 === + === checking 0c1445abb33d === + === checking 65eb34ffc3a8 === === checking 07c648efceeb === === checking c81423bf5a24 === === checking 5ba9a53052ed === @@ -502,11 +502,11 @@ 1ea73414a91b 66f7d451a68b 01241442b3c2 - 0c1445abb33d - 65eb34ffc3a8 2dc09a01254d bebd167eb94d c8d03c1b5e94 + 0c1445abb33d + 65eb34ffc3a8 07c648efceeb c81423bf5a24 5ba9a53052ed @@ -516,14 +516,25 @@ 39bab1cb1cbe 55bf3fdb634f 3e1560705803 + 17b6e6bac221 + 5ce588c2b7c5 + f2bdd828a3aa + a457569c5306 + ad46a4a0fc10 + b115c694654e + 673f5499c8c2 + 900dd066a072 + 97ac964e34b7 + 0d153e3ad632 + c37e7cd9f2bd + 9a67238ad1c4 9729470d9329 884936b34999 - b115c694654e - 8ecb28746ec4 de05b9c29ec7 - d917f77a6439 - c3c7fa726f88 - 97d19fc5236f + d99e0f7dad5b + e4cfd6264623 + fac9e582edd1 + 89a0fe204177 4f5078f7da8a 2bd677d0f13a 3bdb00d5c818 @@ -533,26 +544,15 @@ 2ea3fbf151b5 47c836a1f13e 722d1b8b8942 - 17b6e6bac221 - 5ce588c2b7c5 - f2bdd828a3aa - a457569c5306 - ad46a4a0fc10 4b39f229a0ce d94da36be176 eed373b0090d + b3cf98c3d587 + 8ecb28746ec4 + d917f77a6439 + c3c7fa726f88 + 97d19fc5236f 2472d042ec95 - 673f5499c8c2 - 900dd066a072 - 97ac964e34b7 - 0d153e3ad632 - c37e7cd9f2bd - 9a67238ad1c4 - d99e0f7dad5b - e4cfd6264623 - fac9e582edd1 - 89a0fe204177 - b3cf98c3d587 041e1188f5f1 0484d39906c8 5eec91b12a58 @@ -565,17 +565,22 @@ d6c9e2d27f14 37ad3ab0cddf c7d3029bf731 - 1f4a19f83a29 - 43fc0b77ff07 - 31d7b43cc321 - c713eae2d31f 76151e8066e1 c7c1497fc270 e7135b665740 + c713eae2d31f 82238c0bc950 + 43fc0b77ff07 + 1f4a19f83a29 + 31d7b43cc321 dbde319d43a3 8b79544bb56d 721ba7c5f4ff + 0bab31f71a21 + 40553f55397e + e3e6738c56ce + 790cdfecd168 + 469c700e9ed8 01e29e20ea3f 32b41ca704e1 88714f4125cb @@ -586,11 +591,6 @@ b33fd5ad4c0c cd345198cf12 28be96b80dc1 - 0bab31f71a21 - 40553f55397e - e3e6738c56ce - 790cdfecd168 - 469c700e9ed8 8ae32c3ed670 84d6ec6a8e21 01f771406cab @@ -598,11 +598,11 @@ === checking 1ea73414a91b === === checking 66f7d451a68b === === checking 01241442b3c2 === - === checking 0c1445abb33d === - === checking 65eb34ffc3a8 === === checking 2dc09a01254d === === checking bebd167eb94d === === checking c8d03c1b5e94 === + === checking 0c1445abb33d === + === checking 65eb34ffc3a8 === === checking 07c648efceeb === === checking c81423bf5a24 === === checking 5ba9a53052ed === @@ -612,14 +612,25 @@ === checking 39bab1cb1cbe === === checking 55bf3fdb634f === === checking 3e1560705803 === + === checking 17b6e6bac221 === + === checking 5ce588c2b7c5 === + === checking f2bdd828a3aa === + === checking a457569c5306 === + === checking ad46a4a0fc10 === + === checking b115c694654e === + === checking 673f5499c8c2 === + === checking 900dd066a072 === + === checking 97ac964e34b7 === + === checking 0d153e3ad632 === + === checking c37e7cd9f2bd === + === checking 9a67238ad1c4 === === checking 9729470d9329 === === checking 884936b34999 === - === checking b115c694654e === - === checking 8ecb28746ec4 === === checking de05b9c29ec7 === - === checking d917f77a6439 === - === checking c3c7fa726f88 === - === checking 97d19fc5236f === + === checking d99e0f7dad5b === + === checking e4cfd6264623 === + === checking fac9e582edd1 === + === checking 89a0fe204177 === === checking 4f5078f7da8a === === checking 2bd677d0f13a === === checking 3bdb00d5c818 === @@ -629,26 +640,15 @@ === checking 2ea3fbf151b5 === === checking 47c836a1f13e === === checking 722d1b8b8942 === - === checking 17b6e6bac221 === - === checking 5ce588c2b7c5 === - === checking f2bdd828a3aa === - === checking a457569c5306 === - === checking ad46a4a0fc10 === === checking 4b39f229a0ce === === checking d94da36be176 === === checking eed373b0090d === + === checking b3cf98c3d587 === + === checking 8ecb28746ec4 === + === checking d917f77a6439 === + === checking c3c7fa726f88 === + === checking 97d19fc5236f === === checking 2472d042ec95 === - === checking 673f5499c8c2 === - === checking 900dd066a072 === - === checking 97ac964e34b7 === - === checking 0d153e3ad632 === - === checking c37e7cd9f2bd === - === checking 9a67238ad1c4 === - === checking d99e0f7dad5b === - === checking e4cfd6264623 === - === checking fac9e582edd1 === - === checking 89a0fe204177 === - === checking b3cf98c3d587 === === checking 041e1188f5f1 === === checking 0484d39906c8 === === checking 5eec91b12a58 === @@ -661,17 +661,22 @@ === checking d6c9e2d27f14 === === checking 37ad3ab0cddf === === checking c7d3029bf731 === - === checking 1f4a19f83a29 === - === checking 43fc0b77ff07 === - === checking 31d7b43cc321 === - === checking c713eae2d31f === === checking 76151e8066e1 === === checking c7c1497fc270 === === checking e7135b665740 === + === checking c713eae2d31f === === checking 82238c0bc950 === + === checking 43fc0b77ff07 === + === checking 1f4a19f83a29 === + === checking 31d7b43cc321 === === checking dbde319d43a3 === === checking 8b79544bb56d === === checking 721ba7c5f4ff === + === checking 0bab31f71a21 === + === checking 40553f55397e === + === checking e3e6738c56ce === + === checking 790cdfecd168 === + === checking 469c700e9ed8 === === checking 01e29e20ea3f === === checking 32b41ca704e1 === === checking 88714f4125cb === @@ -682,17 +687,23 @@ === checking b33fd5ad4c0c === === checking cd345198cf12 === === checking 28be96b80dc1 === - === checking 0bab31f71a21 === - === checking 40553f55397e === - === checking e3e6738c56ce === - === checking 790cdfecd168 === - === checking 469c700e9ed8 === === checking 8ae32c3ed670 === === checking 84d6ec6a8e21 === === checking 01f771406cab === $ hg showsort --rev 'Cfinal' --limit 72 - c3c7fa726f88 - 97d19fc5236f + 673f5499c8c2 + 900dd066a072 + 97ac964e34b7 + 0d153e3ad632 + c37e7cd9f2bd + 9a67238ad1c4 + 9729470d9329 + 884936b34999 + de05b9c29ec7 + d99e0f7dad5b + e4cfd6264623 + fac9e582edd1 + 89a0fe204177 4f5078f7da8a 2bd677d0f13a 3bdb00d5c818 @@ -702,26 +713,15 @@ 2ea3fbf151b5 47c836a1f13e 722d1b8b8942 - 17b6e6bac221 - 5ce588c2b7c5 - f2bdd828a3aa - a457569c5306 - ad46a4a0fc10 4b39f229a0ce d94da36be176 eed373b0090d + b3cf98c3d587 + 8ecb28746ec4 + d917f77a6439 + c3c7fa726f88 + 97d19fc5236f 2472d042ec95 - 673f5499c8c2 - 900dd066a072 - 97ac964e34b7 - 0d153e3ad632 - c37e7cd9f2bd - 9a67238ad1c4 - d99e0f7dad5b - e4cfd6264623 - fac9e582edd1 - 89a0fe204177 - b3cf98c3d587 041e1188f5f1 0484d39906c8 5eec91b12a58 @@ -734,17 +734,22 @@ d6c9e2d27f14 37ad3ab0cddf c7d3029bf731 - 1f4a19f83a29 - 43fc0b77ff07 - 31d7b43cc321 - c713eae2d31f 76151e8066e1 c7c1497fc270 e7135b665740 + c713eae2d31f 82238c0bc950 + 43fc0b77ff07 + 1f4a19f83a29 + 31d7b43cc321 dbde319d43a3 8b79544bb56d 721ba7c5f4ff + 0bab31f71a21 + 40553f55397e + e3e6738c56ce + 790cdfecd168 + 469c700e9ed8 01e29e20ea3f 32b41ca704e1 88714f4125cb @@ -755,11 +760,6 @@ b33fd5ad4c0c cd345198cf12 28be96b80dc1 - 0bab31f71a21 - 40553f55397e - e3e6738c56ce - 790cdfecd168 - 469c700e9ed8 8ae32c3ed670 84d6ec6a8e21 01f771406cab @@ -768,17 +768,22 @@ d6c9e2d27f14 37ad3ab0cddf c7d3029bf731 - 1f4a19f83a29 - 43fc0b77ff07 - 31d7b43cc321 - c713eae2d31f 76151e8066e1 c7c1497fc270 e7135b665740 + c713eae2d31f 82238c0bc950 + 43fc0b77ff07 + 1f4a19f83a29 + 31d7b43cc321 dbde319d43a3 8b79544bb56d 721ba7c5f4ff + 0bab31f71a21 + 40553f55397e + e3e6738c56ce + 790cdfecd168 + 469c700e9ed8 01e29e20ea3f 32b41ca704e1 88714f4125cb @@ -789,16 +794,11 @@ b33fd5ad4c0c cd345198cf12 28be96b80dc1 - 0bab31f71a21 - 40553f55397e - e3e6738c56ce - 790cdfecd168 - 469c700e9ed8 8ae32c3ed670 84d6ec6a8e21 01f771406cab $ hg showsort --rev 'Cfinal' --limit 4 - 469c700e9ed8 + 28be96b80dc1 8ae32c3ed670 84d6ec6a8e21 01f771406cab @@ -827,18 +827,18 @@ $ hg showsort --rev 'all()' > ../crisscross.random.order $ python "$RUNTESTDIR/md5sum.py" ../crisscross.*.order - 56271e05099a227fc7c0d6a434c24f0e ../crisscross.random.order - 56271e05099a227fc7c0d6a434c24f0e ../crisscross.source.order + 0ace2b2a63ec70b3b63b661aaee69878 ../crisscross.random.order + 0ace2b2a63ec70b3b63b661aaee69878 ../crisscross.source.order $ diff -u ../crisscross.*.order $ hg showsort --rev 'all()' 1ea73414a91b 66f7d451a68b 01241442b3c2 - 0c1445abb33d - 65eb34ffc3a8 2dc09a01254d bebd167eb94d c8d03c1b5e94 + 0c1445abb33d + 65eb34ffc3a8 07c648efceeb c81423bf5a24 5ba9a53052ed @@ -848,14 +848,25 @@ 39bab1cb1cbe 55bf3fdb634f 3e1560705803 + 17b6e6bac221 + 5ce588c2b7c5 + f2bdd828a3aa + a457569c5306 + ad46a4a0fc10 + b115c694654e + 673f5499c8c2 + 900dd066a072 + 97ac964e34b7 + 0d153e3ad632 + c37e7cd9f2bd + 9a67238ad1c4 9729470d9329 884936b34999 - b115c694654e - 8ecb28746ec4 de05b9c29ec7 - d917f77a6439 - c3c7fa726f88 - 97d19fc5236f + d99e0f7dad5b + e4cfd6264623 + fac9e582edd1 + 89a0fe204177 4f5078f7da8a 2bd677d0f13a 3bdb00d5c818 @@ -865,26 +876,15 @@ 2ea3fbf151b5 47c836a1f13e 722d1b8b8942 - 17b6e6bac221 - 5ce588c2b7c5 - f2bdd828a3aa - a457569c5306 - ad46a4a0fc10 4b39f229a0ce d94da36be176 eed373b0090d + b3cf98c3d587 + 8ecb28746ec4 + d917f77a6439 + c3c7fa726f88 + 97d19fc5236f 2472d042ec95 - 673f5499c8c2 - 900dd066a072 - 97ac964e34b7 - 0d153e3ad632 - c37e7cd9f2bd - 9a67238ad1c4 - d99e0f7dad5b - e4cfd6264623 - fac9e582edd1 - 89a0fe204177 - b3cf98c3d587 041e1188f5f1 0484d39906c8 5eec91b12a58 @@ -897,17 +897,22 @@ d6c9e2d27f14 37ad3ab0cddf c7d3029bf731 - 1f4a19f83a29 - 43fc0b77ff07 - 31d7b43cc321 - c713eae2d31f 76151e8066e1 c7c1497fc270 e7135b665740 + c713eae2d31f 82238c0bc950 + 43fc0b77ff07 + 1f4a19f83a29 + 31d7b43cc321 dbde319d43a3 8b79544bb56d 721ba7c5f4ff + 0bab31f71a21 + 40553f55397e + e3e6738c56ce + 790cdfecd168 + 469c700e9ed8 01e29e20ea3f 32b41ca704e1 88714f4125cb @@ -918,11 +923,6 @@ b33fd5ad4c0c cd345198cf12 28be96b80dc1 - 0bab31f71a21 - 40553f55397e - e3e6738c56ce - 790cdfecd168 - 469c700e9ed8 8ae32c3ed670 84d6ec6a8e21 01f771406cab
--- a/tests/test-stablesort.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-stablesort.t Tue Jan 16 04:35:34 2018 +0100 @@ -10,7 +10,7 @@ > logtemplate = "{rev} {node|short} {desc} {tags}\n" > [alias] > showsort = debugstablesort --template="{node|short}\n" --method basic-mergepoint - > showsorthead = debugstablesort --template="{node|short}\n" --method headcached + > showsorthead = debugstablesort --template="{node|short}\n" --method headondisk > EOF @@ -117,14 +117,14 @@ 4c748ffd1a46 f0f3ef9a6cd5 1d8d22637c2d - 2702dd0c91e7 - bab5d5bf48bd - b4594d867745 e7d9710d9fc6 d62d843c9a01 dcbb326fdec2 + ff43616e5d0f + bab5d5bf48bd + b4594d867745 e46a4836065c - ff43616e5d0f + 2702dd0c91e7 $ hg showsorthead --rev 1d8d22637c2d 1ea73414a91b 66f7d451a68b @@ -214,14 +214,14 @@ === checking 4c748ffd1a46 === === checking f0f3ef9a6cd5 === === checking 1d8d22637c2d === - === checking 2702dd0c91e7 === - === checking bab5d5bf48bd === - === checking b4594d867745 === === checking e7d9710d9fc6 === === checking d62d843c9a01 === === checking dcbb326fdec2 === + === checking ff43616e5d0f === + === checking bab5d5bf48bd === + === checking b4594d867745 === === checking e46a4836065c === - === checking ff43616e5d0f === + === checking 2702dd0c91e7 === Check stability =============== @@ -470,10 +470,10 @@ D $ python "$RUNTESTDIR/md5sum.py" *.all.order - 4f54f623da142833149055fb83022a7e A.all.order - 4f54f623da142833149055fb83022a7e B.all.order - 4f54f623da142833149055fb83022a7e C.all.order - 4f54f623da142833149055fb83022a7e D.all.order + 25e89e555b56ed9e7b51827d58073b77 A.all.order + 25e89e555b56ed9e7b51827d58073b77 B.all.order + 25e89e555b56ed9e7b51827d58073b77 C.all.order + 25e89e555b56ed9e7b51827d58073b77 D.all.order one specific head @@ -697,17 +697,17 @@ 66f7d451a68b 01241442b3c2 2dc09a01254d - abf57d94268b - 529dfc5bb875 e7bd5218ca15 - 6ee532b68cfa - 001194dd78d5 3a367db1fabc a2f58e9c1e56 5f18015f9110 9fff0871d230 4dbf739dd63f d64d500024d1 + abf57d94268b + 529dfc5bb875 + 6ee532b68cfa + 001194dd78d5 0496f0a6a143 1c645e73dbc6 160a7a0adbf4 @@ -719,25 +719,25 @@ 66f7d451a68b 01241442b3c2 2dc09a01254d - abf57d94268b - 529dfc5bb875 e7bd5218ca15 - 6ee532b68cfa - 001194dd78d5 3a367db1fabc a2f58e9c1e56 5f18015f9110 9fff0871d230 4dbf739dd63f d64d500024d1 + abf57d94268b + 529dfc5bb875 + 6ee532b68cfa + 001194dd78d5 0496f0a6a143 1c645e73dbc6 160a7a0adbf4 $ hg showsorthead --rev '160a7a0adbf4' --limit 7 - 5f18015f9110 - 9fff0871d230 - 4dbf739dd63f - d64d500024d1 + abf57d94268b + 529dfc5bb875 + 6ee532b68cfa + 001194dd78d5 0496f0a6a143 1c645e73dbc6 160a7a0adbf4 @@ -770,17 +770,17 @@ === checking 66f7d451a68b === === checking 01241442b3c2 === === checking 2dc09a01254d === - === checking abf57d94268b === - === checking 529dfc5bb875 === === checking e7bd5218ca15 === - === checking 6ee532b68cfa === - === checking 001194dd78d5 === === checking 3a367db1fabc === === checking a2f58e9c1e56 === === checking 5f18015f9110 === === checking 9fff0871d230 === === checking 4dbf739dd63f === === checking d64d500024d1 === + === checking abf57d94268b === + === checking 529dfc5bb875 === + === checking 6ee532b68cfa === + === checking 001194dd78d5 === === checking 0496f0a6a143 === === checking 1c645e73dbc6 === === checking 160a7a0adbf4 === @@ -811,11 +811,11 @@ $ hg showsorthead --rev '160a7a0adbf4' > ../160a7a0adbf4.random.orderhead $ hg showsorthead --rev '4bbfc6078919' > ../4bbfc6078919.random.orderhead $ python "$RUNTESTDIR/md5sum.py" ../multiple.*.order - a6547220a9f004c975e365d9561639dd ../multiple.random.order - a6547220a9f004c975e365d9561639dd ../multiple.source.order + 19b28a58af0311b99159f60944a57213 ../multiple.random.order + 19b28a58af0311b99159f60944a57213 ../multiple.source.order $ python "$RUNTESTDIR/md5sum.py" ../160a7a0adbf4.*.orderhead - 48d8911f53869b32e29da26c56e95119 ../160a7a0adbf4.random.orderhead - 48d8911f53869b32e29da26c56e95119 ../160a7a0adbf4.source.orderhead + 905b0bab9155f65ed2e220382b94e9b9 ../160a7a0adbf4.random.orderhead + 905b0bab9155f65ed2e220382b94e9b9 ../160a7a0adbf4.source.orderhead $ python "$RUNTESTDIR/md5sum.py" ../4bbfc6078919.*.orderhead 3732305a333d59ec50b91db0f5ab696e ../4bbfc6078919.random.orderhead 3732305a333d59ec50b91db0f5ab696e ../4bbfc6078919.source.orderhead @@ -824,17 +824,17 @@ 66f7d451a68b 01241442b3c2 2dc09a01254d - abf57d94268b - 529dfc5bb875 e7bd5218ca15 - 6ee532b68cfa - 001194dd78d5 3a367db1fabc a2f58e9c1e56 5f18015f9110 9fff0871d230 4dbf739dd63f d64d500024d1 + abf57d94268b + 529dfc5bb875 + 6ee532b68cfa + 001194dd78d5 0496f0a6a143 1c645e73dbc6 160a7a0adbf4 @@ -846,17 +846,17 @@ 66f7d451a68b 01241442b3c2 2dc09a01254d - abf57d94268b - 529dfc5bb875 e7bd5218ca15 - 6ee532b68cfa - 001194dd78d5 3a367db1fabc a2f58e9c1e56 5f18015f9110 9fff0871d230 4dbf739dd63f d64d500024d1 + abf57d94268b + 529dfc5bb875 + 6ee532b68cfa + 001194dd78d5 0496f0a6a143 1c645e73dbc6 160a7a0adbf4 @@ -1024,6 +1024,18 @@ 56526aefbff4 23 $ hg showsort --rev 'tip' 1ea73414a91b + 7cc044fdf4a7 + e5c0d969abc4 + ee222cc71ce6 + 448a7ac3ab1f + 5cb8e6902ff3 + 191bac7bf37c + 5188cf52b7b7 + 65e683dd6db4 + 4442c125b80d + 5648bbf0e38b + 6a97ef856f90 + d4422659bc40 66f7d451a68b 01241442b3c2 2dc09a01254d @@ -1033,6 +1045,9 @@ bebd167eb94d c8d03c1b5e94 9f6c364a3574 + 56526aefbff4 + $ hg showsorthead --rev 'tip' + 1ea73414a91b 7cc044fdf4a7 e5c0d969abc4 ee222cc71ce6 @@ -1045,9 +1060,6 @@ 5648bbf0e38b 6a97ef856f90 d4422659bc40 - 56526aefbff4 - $ hg showsorthead --rev 'tip' - 1ea73414a91b 66f7d451a68b 01241442b3c2 2dc09a01254d @@ -1057,42 +1069,30 @@ bebd167eb94d c8d03c1b5e94 9f6c364a3574 - 7cc044fdf4a7 - e5c0d969abc4 - ee222cc71ce6 - 448a7ac3ab1f - 5cb8e6902ff3 - 191bac7bf37c - 5188cf52b7b7 - 65e683dd6db4 - 4442c125b80d - 5648bbf0e38b - 6a97ef856f90 - d4422659bc40 56526aefbff4 $ hg showsorthead --rev 'tip' --limit 12 - e5c0d969abc4 - ee222cc71ce6 - 448a7ac3ab1f - 5cb8e6902ff3 - 191bac7bf37c - 5188cf52b7b7 - 65e683dd6db4 - 4442c125b80d - 5648bbf0e38b 6a97ef856f90 d4422659bc40 + 66f7d451a68b + 01241442b3c2 + 2dc09a01254d + c2c595bcd4c6 + e2317cea05f7 + 588f0bc87ecd + bebd167eb94d + c8d03c1b5e94 + 9f6c364a3574 56526aefbff4 $ hg showsorthead --rev 'tip' --limit 7 - 5188cf52b7b7 - 65e683dd6db4 - 4442c125b80d - 5648bbf0e38b - 6a97ef856f90 - d4422659bc40 + c2c595bcd4c6 + e2317cea05f7 + 588f0bc87ecd + bebd167eb94d + c8d03c1b5e94 + 9f6c364a3574 56526aefbff4 $ hg showsorthead --rev 'tip' --limit 3 - 6a97ef856f90 - d4422659bc40 + c8d03c1b5e94 + 9f6c364a3574 56526aefbff4 $ cd ..
--- a/tests/test-stack-branch.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-stack-branch.t Tue Jan 16 04:35:34 2018 +0100 @@ -181,6 +181,7 @@ $ hg add ggg $ hg commit -m c_g created new head + (consider using topic for lightweight branches. See 'hg help topic') $ echo aaa > hhh $ hg add hhh $ hg commit -m c_h
--- a/tests/test-topic-change.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-change.t Tue Jan 16 04:35:34 2018 +0100 @@ -10,7 +10,7 @@ > [phases] > publish=false > [alias] - > glog = log -G -T "{rev}:{node|short} \{{topics}}\n{desc} ({bookmarks})\n\n" + > glog = log -G -T "{rev}:{node|short} \{{topic}}\n{desc} ({bookmarks})\n\n" > EOF About the glog output: {} contains the topic name and () will contain the bookmark
--- a/tests/test-topic-flow-publish-bare.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-flow-publish-bare.t Tue Jan 16 04:35:34 2018 +0100 @@ -52,10 +52,12 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ mkcommit c_dC0 created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg update 'desc("c_dA0")' 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ mkcommit c_dD0 created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg push -f pushing to $TESTTMP/bare-branch-server searching for changes
--- a/tests/test-topic-flow-single-head.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-flow-single-head.t Tue Jan 16 04:35:34 2018 +0100 @@ -63,6 +63,7 @@ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ mkcommit c_dD0 created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg push -f pushing to $TESTTMP/single-head-server searching for changes
--- a/tests/test-topic-fold.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-fold.t Tue Jan 16 04:35:34 2018 +0100 @@ -78,6 +78,7 @@ $ hg topic --clear $ mkcommit feature3 created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg topic myotherfeature marked working directory as topic: myotherfeature $ mkcommit feature4
--- a/tests/test-topic-push-concurrent-on.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-push-concurrent-on.t Tue Jan 16 04:35:34 2018 +0100 @@ -58,6 +58,7 @@ $ hg add ccc $ hg commit -m 'CC' created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg outgoing -G comparing with $TESTTMP/main (glob) searching for changes @@ -313,6 +314,7 @@ $ hg add ggg $ hg commit -m 'CG' created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg up 'desc(CF)' switching to topic babar 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-topic-push.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-push.t Tue Jan 16 04:35:34 2018 +0100 @@ -54,6 +54,7 @@ $ hg add ccc $ hg commit -m 'CC' created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg outgoing -G comparing with $TESTTMP/main (glob) searching for changes @@ -364,6 +365,7 @@ $ hg add ggg $ hg commit -m 'CG' created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg up 'desc(CF)' switching to topic babar 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
--- a/tests/test-topic-rebase.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-rebase.t Tue Jan 16 04:35:34 2018 +0100 @@ -28,7 +28,7 @@ > hg ci -m "add $1" $2 $3 > } $ logtopic() { - > hg log -G -T "{rev}:{node}\ntopics: {topics}" + > hg log -G -T "{rev}:{node}\ntopics: {topic}" > } Check that rebase keep the topic in the simple case (1 changeset, no merge conflict) @@ -101,6 +101,7 @@ $ echo "A" > file $ hg commit -A -m "default2" file created new head + (consider using topic for lightweight branches. See 'hg help topic') Update the common file in a topic $ hg topic myotherfeature
--- a/tests/test-topic-stack-data.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-stack-data.t Tue Jan 16 04:35:34 2018 +0100 @@ -44,6 +44,7 @@ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved $ mkcommit lake_c created new head + (consider using topic for lightweight branches. See 'hg help topic') Add some topics @@ -114,33 +115,33 @@ unstable: 3 changesets topic: foo $ hg log --graph -T '{desc} ({branch}) [{topic}]' - @ add foo_b (lake) [] + @ add foo_b (lake) [foo] | - o add foo_a (lake) [] + o add foo_a (lake) [foo] | - | o bar1_d (default) [] + | o bar1_d (default) [bar] | | - | | o add bar_e (default) [] + | | o add bar_e (default) [bar] | | | - | | x add bar_d (default) [] + | | x add bar_d (default) [bar] | |/ - | | o add bar_c (default) [] + | | o add bar_c (default) [bar] | |/ - | o add bar_b (default) [] + | o add bar_b (default) [bar] | | - | o add bar_a (default) [] + | o add bar_a (default) [bar] | | - | | o fuz1_a (default) [] + | | o fuz1_a (default) [fuz] | | | - | | | o add fuz_c (default) [] + | | | o add fuz_c (default) [fuz] | | | | - | | | o add fuz_b (default) [] + | | | o add fuz_b (default) [fuz] | | | | - | | | x add fuz_a (default) [] + | | | x add fuz_a (default) [fuz] | | |/ - | | | o add baz_b (default) [] + | | | o add baz_b (default) [baz] | | | | - | | | o add baz_a (default) [] + | | | o add baz_a (default) [baz] | | | | +-------o add lake_c (lake) [] | | | | @@ -173,10 +174,10 @@ quiet version $ hg topic --quiet - bar (5 changesets, 1 troubled, 2 heads) - baz (2 changesets) - foo (2 changesets) - fuz (3 changesets, 2 troubled) + bar + baz + foo + fuz verbose
--- a/tests/test-topic-tutorial.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic-tutorial.t Tue Jan 16 04:35:34 2018 +0100 @@ -53,8 +53,10 @@ finalized (moved to the public phase). They can help users to organize and share their unfinished work. -In this tutorial, we explain how to use topics for local development. In the first part, -there is a central *publishing* server. Anything pushed to the central server will become public and immutable This means no unfinished work should escapes the local repository. +In this tutorial, we explain how to use topics for local development. In the +first part, there is a central *publishing* server. Anything pushed to the +central server will become public and immutable. This means no unfinished work +should escape the local repository. Topic Basics @@ -73,21 +75,21 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; + width=1]; } #endif @@ -123,21 +125,21 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; + width=1]; } #endif @@ -166,21 +168,21 @@ $ hg docgraph -r "topic("food")" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 1 [fillcolor="#9999FF", + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; } #endif @@ -213,31 +215,31 @@ $ hg docgraph -r "topic("food")" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 1 [fillcolor="#9999FF", + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; - 2 [fillcolor="#9999FF", + width=1]; + 2 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=2, pin=true, pos="1,2!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 1 -> 2 [arrowhead=none, penwidth=2.0]; } @@ -288,43 +290,43 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 1 [fillcolor="#9999FF", + width=1]; + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 0 -> 1 [arrowhead=none, penwidth=2.0]; - 2 [fillcolor="#9999FF", + 2 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=2, pin=true, pos="1,2!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 1 -> 2 [arrowhead=none, penwidth=2.0]; } @@ -411,55 +413,55 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 1 [fillcolor="#9999FF", + width=1]; + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 0 -> 1 [arrowhead=none, penwidth=2.0]; - 3 [fillcolor="#9999FF", + 3 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=3, pin=true, pos="1,3!", shape=circle, style=filled, - width=0.5]; + width=1]; 0 -> 3 [arrowhead=none, penwidth=2.0]; - 2 [fillcolor="#9999FF", + 2 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=2, pin=true, pos="1,2!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 1 -> 2 [arrowhead=none, penwidth=2.0]; } @@ -518,60 +520,72 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 3 [fillcolor="#9999FF", + width=1]; + 3 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=3, pin=true, pos="1,3!", shape=circle, style=filled, - width=0.5]; + width=1]; 0 -> 3 [arrowhead=none, penwidth=2.0]; - 4 [fillcolor="#9999FF", + 4 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=4, pin=true, pos="1,4!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 3 -> 4 [arrowhead=none, penwidth=2.0]; - 5 [fillcolor="#9999FF", + 5 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 4 -> 5 [arrowhead=none, penwidth=2.0]; } #endif +There exists a template keyword named "topic" which can be used + + $ hg log -GT "{rev}:{node|short} {topic}\n {desc}" + @ 5:2d50db8b5b4c food + | adding fruits + o 4:4011b46eeb33 food + | adding condiments + o 3:6104862e8b84 + | Adding clothes + o 0:38da43f0a2ea + Shopping list + The topic information will disappear when we publish the changesets: $ hg topics @@ -626,55 +640,55 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 3 [fillcolor="#9999FF", + width=1]; + 3 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=3, pin=true, pos="1,3!", shape=circle, style=filled, - width=0.5]; + width=1]; 0 -> 3 [arrowhead=none, penwidth=2.0]; - 4 [fillcolor="#9999FF", + 4 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=4, pin=true, pos="1,4!", shape=circle, style=filled, - width=0.5]; + width=1]; 3 -> 4 [arrowhead=none, penwidth=2.0]; - 5 [fillcolor="#9999FF", + 5 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; + width=1]; 4 -> 5 [arrowhead=none, penwidth=2.0]; } @@ -695,8 +709,8 @@ Keep working within topics ========================== -Making sure all your new local commit are made within a topic will help your -organise your work. It is possible to ensure this through the Mercurial +Making sure all your new local commit are made within a topic will help you +organize your work. It is possible to ensure this through the Mercurial configuration. For this tutorial, we'll add the config at the repository level: @@ -726,7 +740,7 @@ Working with Multiple Topics ============================ -In the above example, topics do not bring much benefits since you only have one +In the above example, topics do not bring many benefits since you only have one line of development. Topics start to be more useful when you have to work on multiple features at the same time. @@ -895,141 +909,141 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { - graph [rankdir=LR, - splines=polyline - ]; - node [label="\N"]; - 0 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=0, - pin=true, - pos="1,0!", - shape=circle, - style=filled, - width=0.5]; - 3 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=3, - pin=true, - pos="1,3!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 3 [arrowhead=none, - penwidth=2.0]; - 4 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=4, - pin=true, - pos="1,4!", - shape=circle, - style=filled, - width=0.5]; - 3 -> 4 [arrowhead=none, - penwidth=2.0]; - 5 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 4 -> 5 [arrowhead=none, - penwidth=2.0]; - 6 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=6, - pin=true, - pos="1,6!", - shape=pentagon, - style=filled, - width=0.5]; - 5 -> 6 [arrowhead=none, - penwidth=2.0]; - 9 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=9, - pin=true, - pos="1,9!", - shape=pentagon, - style=filled, - width=0.5]; - 5 -> 9 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=11, - pin=true, - pos="1,11!", - shape=circle, - style=filled, - width=0.5]; - 5 -> 11 [arrowhead=none, - penwidth=2.0]; - 7 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=7, - pin=true, - pos="1,7!", - shape=pentagon, - style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, - penwidth=2.0]; - 8 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=8, - pin=true, - pos="1,8!", - shape=pentagon, - style=filled, - width=0.5]; - 7 -> 8 [arrowhead=none, - penwidth=2.0]; - 10 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=10, - pin=true, - pos="1,10!", - shape=pentagon, - style=filled, - width=0.5]; - 9 -> 10 [arrowhead=none, - penwidth=2.0]; - 12 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=12, - pin=true, - pos="1,12!", - shape=circle, - style=filled, - width=0.5]; - 11 -> 12 [arrowhead=none, - penwidth=2.0]; + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=0, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 3 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=3, + pin=true, + pos="1,3!", + shape=circle, + style=filled, + width=1]; + 0 -> 3 [arrowhead=none, + penwidth=2.0]; + 4 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=4, + pin=true, + pos="1,4!", + shape=circle, + style=filled, + width=1]; + 3 -> 4 [arrowhead=none, + penwidth=2.0]; + 5 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=5, + pin=true, + pos="1,5!", + shape=circle, + style=filled, + width=1]; + 4 -> 5 [arrowhead=none, + penwidth=2.0]; + 6 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=6, + pin=true, + pos="1,6!", + shape=pentagon, + style=filled, + width=1]; + 5 -> 6 [arrowhead=none, + penwidth=2.0]; + 9 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=9, + pin=true, + pos="1,9!", + shape=pentagon, + style=filled, + width=1]; + 5 -> 9 [arrowhead=none, + penwidth=2.0]; + 11 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=11, + pin=true, + pos="1,11!", + shape=circle, + style=filled, + width=1]; + 5 -> 11 [arrowhead=none, + penwidth=2.0]; + 7 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=7, + pin=true, + pos="1,7!", + shape=pentagon, + style=filled, + width=1]; + 6 -> 7 [arrowhead=none, + penwidth=2.0]; + 8 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=8, + pin=true, + pos="1,8!", + shape=pentagon, + style=filled, + width=1]; + 7 -> 8 [arrowhead=none, + penwidth=2.0]; + 10 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=10, + pin=true, + pos="1,10!", + shape=pentagon, + style=filled, + width=1]; + 9 -> 10 [arrowhead=none, + penwidth=2.0]; + 12 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=12, + pin=true, + pos="1,12!", + shape=circle, + style=filled, + width=1]; + 11 -> 12 [arrowhead=none, + penwidth=2.0]; } #endif @@ -1238,97 +1252,98 @@ $ hg docgraph -r "t0::" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { - graph [rankdir=LR, - splines=polyline - ]; - node [label="\N"]; - 12 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=12, - pin=true, - pos="1,12!", - shape=circle, - style=filled, - width=0.5]; - 13 [fillcolor="#DFDFFF", - fixedsize=true, - group=default_alt, - height=0.5, - label=13, - pin=true, - pos="2,13!", - shape=pentagon, - style="dotted, filled", - width=0.5]; - 12 -> 13 [arrowhead=none, - penwidth=2.0]; - 18 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=18, - pin=true, - pos="1,18!", - shape=pentagon, - style=filled, - width=0.5]; - 12 -> 18 [arrowhead=none, - penwidth=2.0]; - 16 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=16, - pin=true, - pos="1,16!", - shape=circle, - style=filled, - width=0.5]; - 12 -> 16 [arrowhead=none, - penwidth=2.0]; - 13 -> 18 [arrowhead=none, - minlen=0, - penwidth=2.0, - style=dashed]; - 14 [fillcolor="#FF4F4F", - fixedsize=true, - group=default_alt, - height=0.5, - label=14, - pin=true, - pos="2,14!", - shape=pentagon, - style=filled, - width=0.5]; - 13 -> 14 [arrowhead=none, - penwidth=2.0]; - 15 [fillcolor="#FF4F4F", - fixedsize=true, - group=default_alt, - height=0.5, - label=15, - pin=true, - pos="2,15!", - shape=pentagon, - style=filled, - width=0.5]; - 14 -> 15 [arrowhead=none, - penwidth=2.0]; - 17 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=17, - pin=true, - pos="1,17!", - shape=circle, - style=filled, - width=0.5]; - 16 -> 17 [arrowhead=none, - penwidth=2.0]; + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 12 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=12, + pin=true, + pos="1,12!", + shape=circle, + style=filled, + width=1]; + 13 [fillcolor="#DFDFFF", + fixedsize=true, + group=default_alt, + height=1, + label=13, + pin=true, + pos="2,13!", + shape=pentagon, + style="dotted, filled", + width=1]; + 12 -> 13 [arrowhead=none, + penwidth=2.0]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=18, + pin=true, + pos="1,18!", + shape=pentagon, + style=filled, + width=1]; + 12 -> 18 [arrowhead=none, + penwidth=2.0]; + 16 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=16, + pin=true, + pos="1,16!", + shape=circle, + style=filled, + width=1]; + 12 -> 16 [arrowhead=none, + penwidth=2.0]; + 13 -> 18 [arrowtail=none, + dir=back, + minlen=0, + penwidth=2.0, + style=dashed]; + 14 [fillcolor="#FF4F4F", + fixedsize=true, + group=default_alt, + height=1, + label=14, + pin=true, + pos="2,14!", + shape=pentagon, + style=filled, + width=1]; + 13 -> 14 [arrowhead=none, + penwidth=2.0]; + 15 [fillcolor="#FF4F4F", + fixedsize=true, + group=default_alt, + height=1, + label=15, + pin=true, + pos="2,15!", + shape=pentagon, + style=filled, + width=1]; + 14 -> 15 [arrowhead=none, + penwidth=2.0]; + 17 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=17, + pin=true, + pos="1,17!", + shape=circle, + style=filled, + width=1]; + 16 -> 17 [arrowhead=none, + penwidth=2.0]; } #endif @@ -1418,81 +1433,81 @@ $ hg docgraph -r "t0::" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { - graph [rankdir=LR, - splines=polyline - ]; - node [label="\N"]; - 12 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=12, - pin=true, - pos="1,12!", - shape=circle, - style=filled, - width=0.5]; - 16 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=16, - pin=true, - pos="1,16!", - shape=circle, - style=filled, - width=0.5]; - 12 -> 16 [arrowhead=none, - penwidth=2.0]; - 18 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=18, - pin=true, - pos="1,18!", - shape=pentagon, - style=filled, - width=0.5]; - 12 -> 18 [arrowhead=none, - penwidth=2.0]; - 17 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=17, - pin=true, - pos="1,17!", - shape=circle, - style=filled, - width=0.5]; - 16 -> 17 [arrowhead=none, - penwidth=2.0]; - 19 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=19, - pin=true, - pos="1,19!", - shape=pentagon, - style=filled, - width=0.5]; - 18 -> 19 [arrowhead=none, - penwidth=2.0]; - 20 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=20, - pin=true, - pos="1,20!", - shape=pentagon, - style=filled, - width=0.5]; - 19 -> 20 [arrowhead=none, - penwidth=2.0]; + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 12 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=12, + pin=true, + pos="1,12!", + shape=circle, + style=filled, + width=1]; + 16 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=16, + pin=true, + pos="1,16!", + shape=circle, + style=filled, + width=1]; + 12 -> 16 [arrowhead=none, + penwidth=2.0]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=18, + pin=true, + pos="1,18!", + shape=pentagon, + style=filled, + width=1]; + 12 -> 18 [arrowhead=none, + penwidth=2.0]; + 17 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=17, + pin=true, + pos="1,17!", + shape=circle, + style=filled, + width=1]; + 16 -> 17 [arrowhead=none, + penwidth=2.0]; + 19 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=19, + pin=true, + pos="1,19!", + shape=pentagon, + style=filled, + width=1]; + 18 -> 19 [arrowhead=none, + penwidth=2.0]; + 20 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=20, + pin=true, + pos="1,20!", + shape=pentagon, + style=filled, + width=1]; + 19 -> 20 [arrowhead=none, + penwidth=2.0]; } #endif Multi-headed stack @@ -1600,153 +1615,153 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { - graph [rankdir=LR, - splines=polyline - ]; - node [label="\N"]; - 0 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=0, - pin=true, - pos="1,0!", - shape=circle, - style=filled, - width=0.5]; - 3 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=3, - pin=true, - pos="1,3!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 3 [arrowhead=none, - penwidth=2.0]; - 4 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=4, - pin=true, - pos="1,4!", - shape=circle, - style=filled, - width=0.5]; - 3 -> 4 [arrowhead=none, - penwidth=2.0]; - 5 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 4 -> 5 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=11, - pin=true, - pos="1,11!", - shape=circle, - style=filled, - width=0.5]; - 5 -> 11 [arrowhead=none, - penwidth=2.0]; - 12 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=12, - pin=true, - pos="1,12!", - shape=circle, - style=filled, - width=0.5]; - 11 -> 12 [arrowhead=none, - penwidth=2.0]; - 16 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=16, - pin=true, - pos="1,16!", - shape=circle, - style=filled, - width=0.5]; - 12 -> 16 [arrowhead=none, - penwidth=2.0]; - 18 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=18, - pin=true, - pos="1,18!", - shape=pentagon, - style=filled, - width=0.5]; - 12 -> 18 [arrowhead=none, - penwidth=2.0]; - 17 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=17, - pin=true, - pos="1,17!", - shape=circle, - style=filled, - width=0.5]; - 16 -> 17 [arrowhead=none, - penwidth=2.0]; - 19 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=19, - pin=true, - pos="1,19!", - shape=pentagon, - style=filled, - width=0.5]; - 18 -> 19 [arrowhead=none, - penwidth=2.0]; - 21 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=21, - pin=true, - pos="1,21!", - shape=pentagon, - style=filled, - width=0.5]; - 18 -> 21 [arrowhead=none, - penwidth=2.0]; - 20 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=20, - pin=true, - pos="1,20!", - shape=pentagon, - style=filled, - width=0.5]; - 19 -> 20 [arrowhead=none, - penwidth=2.0]; + strict digraph "Mercurial graph" { + graph [rankdir=LR, + splines=polyline + ]; + node [label="\N"]; + 0 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=0, + pin=true, + pos="1,0!", + shape=circle, + style=filled, + width=1]; + 3 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=3, + pin=true, + pos="1,3!", + shape=circle, + style=filled, + width=1]; + 0 -> 3 [arrowhead=none, + penwidth=2.0]; + 4 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=4, + pin=true, + pos="1,4!", + shape=circle, + style=filled, + width=1]; + 3 -> 4 [arrowhead=none, + penwidth=2.0]; + 5 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=5, + pin=true, + pos="1,5!", + shape=circle, + style=filled, + width=1]; + 4 -> 5 [arrowhead=none, + penwidth=2.0]; + 11 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=11, + pin=true, + pos="1,11!", + shape=circle, + style=filled, + width=1]; + 5 -> 11 [arrowhead=none, + penwidth=2.0]; + 12 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=12, + pin=true, + pos="1,12!", + shape=circle, + style=filled, + width=1]; + 11 -> 12 [arrowhead=none, + penwidth=2.0]; + 16 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=16, + pin=true, + pos="1,16!", + shape=circle, + style=filled, + width=1]; + 12 -> 16 [arrowhead=none, + penwidth=2.0]; + 18 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=18, + pin=true, + pos="1,18!", + shape=pentagon, + style=filled, + width=1]; + 12 -> 18 [arrowhead=none, + penwidth=2.0]; + 17 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=17, + pin=true, + pos="1,17!", + shape=circle, + style=filled, + width=1]; + 16 -> 17 [arrowhead=none, + penwidth=2.0]; + 19 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=19, + pin=true, + pos="1,19!", + shape=pentagon, + style=filled, + width=1]; + 18 -> 19 [arrowhead=none, + penwidth=2.0]; + 21 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=21, + pin=true, + pos="1,21!", + shape=pentagon, + style=filled, + width=1]; + 18 -> 21 [arrowhead=none, + penwidth=2.0]; + 20 [fillcolor="#7F7FFF", + fixedsize=true, + group=default, + height=1, + label=20, + pin=true, + pos="1,20!", + shape=pentagon, + style=filled, + width=1]; + 19 -> 20 [arrowhead=none, + penwidth=2.0]; } #endif @@ -1808,7 +1823,7 @@ added 4 changesets with 4 changes to 1 files (+1 heads) 8 new obsolescence markers -Pushing the new topic branch to a non publishing server did not require +Pushing the new topic branch to a non-publishing server did not require --force. As long as new heads are on their own topic, Mercurial will not complain about them. @@ -1856,7 +1871,7 @@ adding file changes added 1 changesets with 1 changes to 1 files -And retrieve them on the first client: +And retrieve them from the first client: $ cd ../client
--- a/tests/test-topic.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-topic.t Tue Jan 16 04:35:34 2018 +0100 @@ -610,6 +610,7 @@ $ echo fran? >> beta $ hg ci -m 'fran?' created new head + (consider using topic for lightweight branches. See 'hg help topic') $ hg log -Gr 'draft()' @ changeset: 10:4073470c35e1 | tag: tip
--- a/tests/test-tutorial.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-tutorial.t Tue Jan 16 04:35:34 2018 +0100 @@ -133,43 +133,43 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 1 [fillcolor="#9999FF", + width=1]; + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 0 -> 1 [arrowhead=none, penwidth=2.0]; - 2 [fillcolor="#9999FF", + 2 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=2, pin=true, pos="1,2!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 1 -> 2 [arrowhead=none, penwidth=2.0]; } @@ -212,43 +212,43 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 1 [fillcolor="#9999FF", + width=1]; + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 0 -> 1 [arrowhead=none, penwidth=2.0]; - 2 [fillcolor="#9999FF", + 2 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=2, pin=true, pos="1,2!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 1 -> 2 [arrowhead=none, penwidth=2.0]; } @@ -284,44 +284,42 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 1 [fillcolor="#9999FF", + width=1]; + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 0 -> 1 [arrowhead=none, penwidth=2.0]; 4 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=4, + height=1, + label=3, pin=true, pos="1,4!", shape=pentagon, style=filled, - width=0.5]; - 1 -> 4 [arrowhead=none, penwidth=2.0]; } #endif @@ -384,56 +382,39 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 1 [fillcolor="#9999FF", + width=1]; + 1 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=1, pin=true, pos="1,1!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 0 -> 1 [arrowhead=none, penwidth=2.0]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, - penwidth=2.0]; - 4 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, + height=1, label=4, pin=true, pos="1,4!", - shape=pentagon, - style=filled, - width=0.5]; - 1 -> 4 [arrowhead=none, penwidth=2.0]; } #endif @@ -463,43 +444,39 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; 7 [fillcolor="#9999FF", @@ -565,43 +542,39 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; 7 [fillcolor="#9999FF", @@ -685,80 +658,42 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=pentagon, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; - 7 [fillcolor="#9999FF", - fixedsize=true, - group=default, height=0.5, - label=7, - pin=true, - pos="1,7!", - shape=pentagon, - style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, - penwidth=2.0]; - 9 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=9, - pin=true, - pos="1,9!", - shape=pentagon, - style=filled, - width=0.5]; - 7 -> 9 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=11, - pin=true, - pos="1,11!", - shape=pentagon, - style=filled, - width=0.5]; - 7 -> 11 [arrowhead=none, penwidth=2.0]; } #endif @@ -829,61 +764,25 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 11 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, - label=6, - pin=true, - pos="1,6!", - shape=circle, - style=filled, - width=0.5]; - 5 -> 6 [arrowhead=none, - penwidth=2.0]; - 7 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=7, - pin=true, - pos="1,7!", - shape=circle, - style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, + height=1, label=11, pin=true, pos="1,11!", @@ -901,8 +800,6 @@ pos="1,12!", shape=pentagon, style=filled, - width=0.5]; - 11 -> 12 [arrowhead=none, penwidth=2.0]; } #endif @@ -936,6 +833,7 @@ -a --all uncommit all changes when no arguments given -r --rev VALUE revert commit content to REV instead + --revert discard working directory changes after uncommit -n --note VALUE store a note on uncommit -I --include PATTERN [+] include names matching the given patterns -X --exclude PATTERN [+] exclude names matching the given patterns @@ -1122,62 +1020,20 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, - penwidth=2.0]; - 6 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=6, - pin=true, - pos="1,6!", - shape=circle, - style=filled, - width=0.5]; - 5 -> 6 [arrowhead=none, - penwidth=2.0]; - 7 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=7, - pin=true, - pos="1,7!", - shape=circle, - style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=11, pin=true, pos="1,11!", shape=circle, @@ -1194,8 +1050,6 @@ pos="1,14!", shape=pentagon, style=filled, - width=0.5]; - 11 -> 14 [arrowhead=none, penwidth=2.0]; } #endif @@ -1238,108 +1092,20 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, - penwidth=2.0]; - 6 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=6, - pin=true, - pos="1,6!", - shape=circle, - style=filled, - width=0.5]; - 5 -> 6 [arrowhead=none, - penwidth=2.0]; - 7 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=7, - pin=true, - pos="1,7!", - shape=circle, - style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=11, - pin=true, - pos="1,11!", - shape=circle, - style=filled, - width=0.5]; - 7 -> 11 [arrowhead=none, - penwidth=2.0]; - 12 [fillcolor="#DFDFFF", - fixedsize=true, - group=default_alt, - height=0.5, - label=12, - pin=true, - pos="2,12!", - shape=pentagon, - style="dotted, filled", - width=0.5]; - 11 -> 12 [arrowhead=none, - penwidth=2.0]; - 14 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=14, - pin=true, - pos="1,14!", - shape=pentagon, - style=filled, - width=0.5]; - 11 -> 14 [arrowhead=none, - penwidth=2.0]; - 12 -> 14 [arrowhead=none, - minlen=0, - penwidth=2.0, - style=dashed]; - 15 [fillcolor="#FF4F4F", - fixedsize=true, - group=default_alt, - height=0.5, - label=15, - pin=true, - pos="2,15!", - shape=pentagon, - style=filled, - width=0.5]; - 12 -> 15 [arrowhead=none, penwidth=2.0]; } #endif @@ -1400,92 +1166,33 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", + penwidth=2.0]; + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, - label=5, - pin=true, - pos="1,5!", - shape=circle, - style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, - penwidth=2.0]; - 6 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=circle, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; - 7 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=7, - pin=true, - pos="1,7!", - shape=circle, - style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, - penwidth=2.0]; - 11 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=11, - pin=true, - pos="1,11!", - shape=circle, - style=filled, - width=0.5]; - 7 -> 11 [arrowhead=none, - penwidth=2.0]; - 14 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=14, - pin=true, - pos="1,14!", - shape=pentagon, - style=filled, - width=0.5]; - 11 -> 14 [arrowhead=none, - penwidth=2.0]; - 16 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=16, - pin=true, - pos="1,16!", - shape=pentagon, - style=filled, - width=0.5]; - 14 -> 16 [arrowhead=none, penwidth=2.0]; } #endif @@ -1510,8 +1217,6 @@ pulling from $TESTTMP/local (glob) searching for changes no changes found - working directory parent is obsolete! (bf1b0d202029) - (use 'hg evolve' to update to its successor: ee942144f952) Now let's see where we are, and update to the successor. @@ -1565,104 +1270,71 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=circle, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; - 7 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=7, pin=true, pos="1,7!", shape=circle, style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, penwidth=2.0]; - 11 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=11, pin=true, pos="1,11!", shape=circle, style=filled, - width=0.5]; - 7 -> 11 [arrowhead=none, penwidth=2.0]; - 14 [fillcolor="#9999FF", + 14 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=14, pin=true, pos="1,14!", shape=pentagon, style=filled, - width=0.5]; - 11 -> 14 [arrowhead=none, penwidth=2.0]; - 16 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=16, pin=true, pos="1,16!", shape=pentagon, style=filled, - width=0.5]; - 14 -> 16 [arrowhead=none, - penwidth=2.0]; - 17 [fillcolor="#9999FF", - fixedsize=true, - group=default, - height=0.5, - label=17, - pin=true, - pos="1,17!", - shape=pentagon, - style=filled, - width=0.5]; - 16 -> 17 [arrowhead=none, penwidth=2.0]; } #endif @@ -1701,62 +1373,50 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=circle, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; - 7 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=7, pin=true, pos="1,7!", shape=circle, style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, penwidth=2.0]; - 11 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=11, pin=true, pos="1,11!", shape=circle, @@ -1773,32 +1433,22 @@ pos="1,14!", shape=pentagon, style=filled, - width=0.5]; - 11 -> 14 [arrowhead=none, penwidth=2.0]; 16 [fillcolor="#DFDFFF", fixedsize=true, group=default_alt, - height=0.5, - label=16, pin=true, pos="2,16!", shape=pentagon, style="dotted, filled", - width=0.5]; - 14 -> 16 [arrowhead=none, penwidth=2.0]; 17 [fillcolor="#FF4F4F", fixedsize=true, group=default_alt, - height=0.5, - label=17, pin=true, pos="2,17!", shape=pentagon, style=filled, - width=0.5]; - 16 -> 17 [arrowhead=none, penwidth=2.0]; } #endif @@ -1810,7 +1460,7 @@ $ hg docgraph -r "orphan()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; @@ -1818,13 +1468,11 @@ 17 [fillcolor="#FF4F4F", fixedsize=true, group=default_alt, - height=0.5, - label=17, pin=true, pos="1,17!", shape=pentagon, style=filled, - width=0.5]; + width=1]; } #endif @@ -1854,62 +1502,50 @@ $ hg docgraph -r "all()" --sphinx-directive --rankdir LR #rest-ignore .. graphviz:: - strict digraph { + strict digraph "Mercurial graph" { graph [rankdir=LR, splines=polyline ]; node [label="\N"]; - 0 [fillcolor="#9999FF", + 0 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=0, pin=true, pos="1,0!", shape=circle, style=filled, - width=0.5]; - 5 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, + height=1, label=5, pin=true, pos="1,5!", shape=circle, style=filled, - width=0.5]; - 0 -> 5 [arrowhead=none, penwidth=2.0]; - 6 [fillcolor="#9999FF", + 6 [fillcolor="#7F7FFF", fixedsize=true, group=default, - height=0.5, + height=1, label=6, pin=true, pos="1,6!", shape=circle, style=filled, - width=0.5]; + width=1]; 5 -> 6 [arrowhead=none, penwidth=2.0]; - 7 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=7, pin=true, pos="1,7!", shape=circle, style=filled, - width=0.5]; - 6 -> 7 [arrowhead=none, penwidth=2.0]; - 11 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=11, pin=true, pos="1,11!", shape=circle, @@ -1926,20 +1562,13 @@ pos="1,14!", shape=pentagon, style=filled, - width=0.5]; - 11 -> 14 [arrowhead=none, penwidth=2.0]; - 18 [fillcolor="#9999FF", fixedsize=true, group=default, - height=0.5, - label=18, pin=true, pos="1,18!", shape=pentagon, style=filled, - width=0.5]; - 14 -> 18 [arrowhead=none, penwidth=2.0]; } #endif
--- a/tests/test-uncommit.t Sat Dec 16 23:40:39 2017 +0100 +++ b/tests/test-uncommit.t Tue Jan 16 04:35:34 2018 +0100 @@ -459,3 +459,54 @@ R g R m R n + +Testing the --revert flag of `hg uncommit` + +When working directory before uncommit is clean + + $ hg amend + $ hg status + ? b + + $ hg diff -c . --stat + aa | 1 + + b | 1 - + c | 1 - + d | 1 + + e | 1 + + f | 1 - + ff | 1 + + g | 1 - + h | 1 + + j | 1 + + k | 1 + + l | 1 + + m | 1 - + n | 1 - + o | 1 + + 15 files changed, 9 insertions(+), 6 deletions(-) + $ hg uncommit --revert --all + new changeset is empty + (use 'hg prune .' to remove it) + $ hg status + +When working directory is dirty before uncommit + + $ echo foo > a + $ echo foo > b + $ echo foo > c + $ hg status + M a + M b + M c + $ hg amend + $ echo foo > foo + $ hg add foo + $ hg status + A foo + + $ hg uncommit --revert --all + new changeset is empty + (use 'hg prune .' to remove it) + $ hg status + ? foo