Patchwork [4,of,4] tests: add a new test for merging with memctx (RFC DO NOT COMMIT)

login
register
mail settings
Submitter Sean Farley
Date Aug. 19, 2014, 2:42 a.m.
Message ID <169eaa48089acce06eb8.1408408961@1.0.0.127.in-addr.arpa>
Download mbox | patch
Permalink /patch/5494/
State Changes Requested
Headers show

Comments

Sean Farley - Aug. 19, 2014, 2:42 a.m.
# HG changeset patch
# User Sean Farley <sean.michael.farley@gmail.com>
# Date 1408408797 18000
#      Mon Aug 18 19:39:57 2014 -0500
# Node ID 169eaa48089acce06eb8afa95e1826cd217452ef
# Parent  ed4082b72da600548d6c9ecec102a3639e9bf3e0
tests: add a new test for merging with memctx (RFC DO NOT COMMIT)

Currently, the dirstate isn't updated for some reason.
Pierre-Yves David - Aug. 19, 2014, 7:12 a.m.
On 08/18/2014 07:42 PM, Sean Farley wrote:
> # HG changeset patch
> # User Sean Farley <sean.michael.farley@gmail.com>
> # Date 1408408797 18000
> #      Mon Aug 18 19:39:57 2014 -0500
> # Node ID 169eaa48089acce06eb8afa95e1826cd217452ef
> # Parent  ed4082b72da600548d6c9ecec102a3639e9bf3e0
> tests: add a new test for merging with memctx (RFC DO NOT COMMIT)
>
> Currently, the dirstate isn't updated for some reason.
>
> diff --git a/tests/test-merge-memctx.t b/tests/test-merge-memctx.t
> new file mode 100644
> --- /dev/null
> +++ b/tests/test-merge-memctx.t
> @@ -0,0 +1,86 @@
> +
> +Create a python script to test merging with memctx
> +
> +  $ cat > memmerge.py << EOF
> +  > #!/usr/bin/env python
> +  > from mercurial import context, hg, merge, ui as uimod
> +  > from mercurial.node import nullid
> +  >
> +  > ui = uimod.ui()
> +  > myrepo = hg.repository(ui, '.')

What about adding a new command in an extension instead so that you have 
something somewhat clean ?

> +  >
> +  > ctxa = myrepo.changectx(2)
> +  > ctxb = myrepo.changectx(3)
> +  > orig = myrepo['.']
> +  >
> +  > # build a memctx off of ctxa (but set parents to ctxa and ctxb)
> +  > rctx = context.memctx(myrepo, [ctxa.node(), ctxb.node()], 'test merge',
> +  >                       ctxa.files(), ctxa, user=ctxa.user(), date=ctxa.date(),
> +  >                       extra=ctxa.extra())
> +  >
> +  > stats = merge.update(myrepo, ctxa.node(), True, True, False, ctxa.p1().node(), rctx=rctx)
> +  >
> +  > del rctx._status
> +  > del rctx._manifest

Why is this necessary ?

> +  >
> +  > wlock = myrepo.wlock()
> +  > try:
> +  >     node = myrepo.commitctx(rctx)
> +  >     myrepo.setparents(orig.node(), nullid)

Why do you need to set parent afterward? commitctx with a memctx is not 
supposed to change the working director parent. Isn't it?

> +  >     myrepo.dirstate.write()

Note that you dirstate is not going to rewrite itself up. See the 
`_uncommitdirstate` function in evolve for example of dirstate cleanup 
(probably stolen from somewhere in core)

But I'm a bit puzzle by why the dirstate need to be touched at all as 
all operation should have happened in memory (same question for set parents)


> +  > finally:
> +  >     wlock.release()
> +  > EOF
> +
> +The test requires a repo with two heads
> +
> +  $ hg init main
> +  $ cd main
> +  $ echo line1 > a
> +  $ hg commit -Am0
> +  adding a
> +  $ echo lineA > b
> +  $ hg commit -Am1
> +  adding b
> +  $ echo line2 >> a
> +  $ hg commit -Am2
> +  $ hg update 1
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ echo lineB >> b
> +  $ hg commit -Am3
> +  created new head
> +
> +
> +Merge with a dirty working directory
> +
> +  $ echo dirty >> b
> +  $ python $TESTTMP/memmerge.py
> +  $ hg log -pr tip
> +  changeset:   4:d17d631aeace
> +  tag:         tip
> +  parent:      2:fc28dc423489
> +  parent:      3:c9ea6e4408ad
> +  user:        test
> +  date:        Thu Jan 01 00:00:00 1970 +0000
> +  summary:     test merge
> +
> +  diff -r fc28dc423489 -r d17d631aeace b
> +  --- a/b	Thu Jan 01 00:00:00 1970 +0000
> +  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
> +  @@ -1,1 +1,2 @@
> +   lineA
> +  +lineB
> +
> +Make sure the directory is still dirty
> +
> +  $ hg status
> +  M b
> +
> +  $ hg diff --git --nodates
> +  diff --git a/b b/b
> +  --- a/b
> +  +++ b/b
> +  @@ -1,2 +1,3 @@
> +   lineA
> +   lineB
> +  +dirty
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
Sean Farley - Aug. 20, 2014, 8:02 p.m.
Pierre-Yves David writes:

> On 08/18/2014 07:42 PM, Sean Farley wrote:
>> # HG changeset patch
>> # User Sean Farley <sean.michael.farley@gmail.com>
>> # Date 1408408797 18000
>> #      Mon Aug 18 19:39:57 2014 -0500
>> # Node ID 169eaa48089acce06eb8afa95e1826cd217452ef
>> # Parent  ed4082b72da600548d6c9ecec102a3639e9bf3e0
>> tests: add a new test for merging with memctx (RFC DO NOT COMMIT)
>>
>> Currently, the dirstate isn't updated for some reason.
>>
>> diff --git a/tests/test-merge-memctx.t b/tests/test-merge-memctx.t
>> new file mode 100644
>> --- /dev/null
>> +++ b/tests/test-merge-memctx.t
>> @@ -0,0 +1,86 @@
>> +
>> +Create a python script to test merging with memctx
>> +
>> +  $ cat > memmerge.py << EOF
>> +  > #!/usr/bin/env python
>> +  > from mercurial import context, hg, merge, ui as uimod
>> +  > from mercurial.node import nullid
>> +  >
>> +  > ui = uimod.ui()
>> +  > myrepo = hg.repository(ui, '.')
>
> What about adding a new command in an extension instead so that you have 
> something somewhat clean ?

Because that was too much work. I'd rather fix the manifest and status
stuff below first.

>> +  >
>> +  > ctxa = myrepo.changectx(2)
>> +  > ctxb = myrepo.changectx(3)
>> +  > orig = myrepo['.']
>> +  >
>> +  > # build a memctx off of ctxa (but set parents to ctxa and ctxb)
>> +  > rctx = context.memctx(myrepo, [ctxa.node(), ctxb.node()], 'test merge',
>> +  >                       ctxa.files(), ctxa, user=ctxa.user(), date=ctxa.date(),
>> +  >                       extra=ctxa.extra())
>> +  >
>> +  > stats = merge.update(myrepo, ctxa.node(), True, True, False, ctxa.p1().node(), rctx=rctx)
>> +  >
>> +  > del rctx._status
>> +  > del rctx._manifest
>
> Why is this necessary ?

Because both of those variables are cached before changing the data. I'd
like the cache to be updated after all the changes are made and am
looking into that now.

>> +  >
>> +  > wlock = myrepo.wlock()
>> +  > try:
>> +  >     node = myrepo.commitctx(rctx)
>> +  >     myrepo.setparents(orig.node(), nullid)
>
> Why do you need to set parent afterward? commitctx with a memctx is not 
> supposed to change the working director parent. Isn't it?

Correct, but merge.update does call repo.setparents. My updated work
doesn't need to do this hack.

>> +  >     myrepo.dirstate.write()
>
> Note that you dirstate is not going to rewrite itself up. See the 
> `_uncommitdirstate` function in evolve for example of dirstate cleanup 
> (probably stolen from somewhere in core)

There's something really weird going on with the dirstate that I can't
pin down yet. I can demonstrate it better with my new series.

> But I'm a bit puzzle by why the dirstate need to be touched at all as 
> all operation should have happened in memory (same question for set parents)

I think something is going on with repo.commitctx but I'm not sure yet.

Patch

diff --git a/tests/test-merge-memctx.t b/tests/test-merge-memctx.t
new file mode 100644
--- /dev/null
+++ b/tests/test-merge-memctx.t
@@ -0,0 +1,86 @@ 
+
+Create a python script to test merging with memctx
+
+  $ cat > memmerge.py << EOF
+  > #!/usr/bin/env python
+  > from mercurial import context, hg, merge, ui as uimod
+  > from mercurial.node import nullid
+  > 
+  > ui = uimod.ui()
+  > myrepo = hg.repository(ui, '.')
+  > 
+  > ctxa = myrepo.changectx(2)
+  > ctxb = myrepo.changectx(3)
+  > orig = myrepo['.']
+  > 
+  > # build a memctx off of ctxa (but set parents to ctxa and ctxb)
+  > rctx = context.memctx(myrepo, [ctxa.node(), ctxb.node()], 'test merge',
+  >                       ctxa.files(), ctxa, user=ctxa.user(), date=ctxa.date(),
+  >                       extra=ctxa.extra())
+  > 
+  > stats = merge.update(myrepo, ctxa.node(), True, True, False, ctxa.p1().node(), rctx=rctx)
+  > 
+  > del rctx._status
+  > del rctx._manifest
+  > 
+  > wlock = myrepo.wlock()
+  > try:
+  >     node = myrepo.commitctx(rctx)
+  >     myrepo.setparents(orig.node(), nullid)
+  >     myrepo.dirstate.write()
+  > finally:
+  >     wlock.release()
+  > EOF
+
+The test requires a repo with two heads
+
+  $ hg init main
+  $ cd main
+  $ echo line1 > a
+  $ hg commit -Am0
+  adding a
+  $ echo lineA > b
+  $ hg commit -Am1
+  adding b
+  $ echo line2 >> a
+  $ hg commit -Am2
+  $ hg update 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo lineB >> b
+  $ hg commit -Am3
+  created new head
+
+
+Merge with a dirty working directory
+
+  $ echo dirty >> b
+  $ python $TESTTMP/memmerge.py
+  $ hg log -pr tip
+  changeset:   4:d17d631aeace
+  tag:         tip
+  parent:      2:fc28dc423489
+  parent:      3:c9ea6e4408ad
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     test merge
+  
+  diff -r fc28dc423489 -r d17d631aeace b
+  --- a/b	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/b	Thu Jan 01 00:00:00 1970 +0000
+  @@ -1,1 +1,2 @@
+   lineA
+  +lineB
+  
+Make sure the directory is still dirty
+
+  $ hg status
+  M b
+
+  $ hg diff --git --nodates
+  diff --git a/b b/b
+  --- a/b
+  +++ b/b
+  @@ -1,2 +1,3 @@
+   lineA
+   lineB
+  +dirty