{"id":194,"date":"2011-05-26T13:36:25","date_gmt":"2011-05-26T20:36:25","guid":{"rendered":"http:\/\/blog.mozilla.org\/sfink\/?p=194"},"modified":"2021-06-13T14:08:56","modified_gmt":"2021-06-13T21:08:56","slug":"record-your-freshness","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/sfink\/2011\/05\/26\/record-your-freshness\/","title":{"rendered":"Record your freshness"},"content":{"rendered":"<p>I often like to split patches up into independent pieces, for ease of reviewing by both reviewers and myself. You can split off preparatory refactorings, low-level mechanism from high-level users, features from tests, etc., making it much easier to evaluate the sanity of each piece.<\/p>\n<p>But it&#8217;s something of a pain to do. If I&#8217;ve been hacking along and accumulated a monster patch, with stock hg and mq I&#8217;d do:<\/p>\n<pre>  hg qref -X '*'                  # get all the changes in the working directory; only\r\n                                  # needed if you've been qref'ing along the way\r\n  hg qref -I '...pattern...'      # put in any touched files\r\n  hg qnew temp                    # stash away the rest so you can edit the patch\r\n  hg qpop\r\n  hg qpop                         # go back to unpatched version\r\n  emacs $(hg root --mq)\/<em>patchname<\/em> # hack out the pieces you don't want,\r\n                                  # put them in \/tmp\/p or somewhere...\r\n  hg qpush                        # reapply just the parts you want\r\n  patch -p1 &lt; \/tmp\/p\r\n  ...                             # you get the point. There'll be a qfold somewhere in here...<\/pre>\n<p>and on and on. It&#8217;s a major pain. I even started working on a web-based patch munging tool because I was doing it so often.<\/p>\n<p>Then I discovered <strong>qcrecord<\/strong>, part of the <strong>crecord<\/strong> extension. It is teh awesome with a capital T (and A, but this is a family blog). It gives you a mostly-spiffy-but-slightly-clunky curses (textual) interface to select which files to include, and within those files which patch chunks to include, and within those chunks which <em>individual lines<\/em> to include. That last part, especially, is way cool &#8212; it lets you do things that you&#8217;d have to be crazy to attempt working with the raw patches, and are a major nuisance with the raw files.<\/p>\n<p>Assuming you are again starting with a huge patch that you&#8217;ve been qreffing, the workflow goes something like:<\/p>\n<pre>  hg qref -X '*'\r\n  hg qcrecord my-patch-part1\r\n  hg qcrecord my-patch-part2\r\n  hg qcrecord my-patch-part3\r\n  hg qpop -a\r\n  hg qrm original-patchname\r\n  hg qpush -a<\/pre>\n<p>Way, way nicer. No more dangerous direct edits of patch files. But what&#8217;s that messy business about nuking the original patch? Hold that thought.<\/p>\n<p>Now that you have a nicely split-up patch series, you&#8217;ll be wanting to edit various parts of it. As usual with mq, you qpop or qgoto to the patch you want to hack on, then edit it, and finally qref (qrefresh). But many times you&#8217;ll end up putting in some bits and pieces that really belong in the other patches. So if you were working on my-patch-part2 and made some changes that really belong in my-patch-part3, you do something like:<\/p>\n<pre>  hg qcrecord piece-meant-for-part3             # only select the part intended for part3\r\n  hg qnew remaining-updates-for-part2           # make a patch with the rest of the updates, to go into part2\r\n  hg qgoto my-patch-part2\r\n  hg qpush --move remaining-updates-for-part2   # now we have part2 and its updates adjacent\r\n  hg qpop\r\n  hg qfold remaining-updates-for-part2          # fold them together, producing a final part2\r\n  hg qpush\r\n  hg qfold my-patch-part3                       # fold in part3 with its updates from the beginning\r\n  hg qmv my-patch-part3                         # and rename, mangling the comment<\/pre>\n<p>or at least, that&#8217;s what I generally do. If I were smarter, I would use qcrecord to pick out the remaining updates for part2, making it just:<\/p>\n<pre>  hg qcrecord more-part2    # select everything intended for part2\r\n  hg qnew update-part3      # make a patch with the rest, intended for part3\r\n  hg qfold my-patch-part3   # fold to make a final part3\r\n  hg qmv my-patch-part3     # ...with the wrong name, so fix and mess up the comment\r\n  hg qgoto my-patch-part2\r\n  hg qfold more-part2       # and make a final part2<\/pre>\n<p>but that&#8217;s still a mess. The fundamental problem is that, as great as qcrecord is, it <em>always wants to create a new patch.<\/em> And you don&#8217;t.<\/p>\n<p>Enter <strong>qcrefresh<\/strong>. It doesn&#8217;t exist, but you can get it by replacing your stock crecord with<\/p>\n<pre>  hg clone https:\/\/sfink@bitbucket.org\/sfink\/crecord # Obsolete!<\/pre>\n<p><strong>Update:<\/strong> it has been merged into the main crecord repo! Use<\/p>\n<pre>\u00a0 hg clone https:\/\/bitbucket.org\/edgimar\/crecord<\/pre>\n<p>It does the obvious thing &#8212; it does the equivalent of a qrefresh, except it uses the crecord interface to select what parts should end up in the current patch. So now the above is:<\/p>\n<pre>  hg qcref                 # Keep everything you want for the current patch\r\n  hg qnew update-part3\r\n  hg qfold my-patch-part3\r\n  hg qmv my-patch-part3<\/pre>\n<p>Still a little bit of juggling (though you could alias the latter 3 commands in your ~\/.hgrc, I guess.) It would be nice if qfold had a &#8220;reverse fold&#8221; option.<\/p>\n<p>Finally, when splitting up a large patch you often want to keep the original patch&#8217;s name and comment, so you&#8217;d really do:<\/p>\n<pre>  hg qcref                 # keep just the parts you want in the main patch\r\n  hg qcrec my-patch-part2  # make a final part2\r\n  hg qcrec my-patch-part3  # make a final part3<\/pre>\n<p>And life is good.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I often like to split patches up into independent pieces, for ease of reviewing by both reviewers and myself. You can split off preparatory refactorings, low-level mechanism from high-level users, features from tests, etc., making it much easier to evaluate the sanity of each piece. But it&#8217;s something of a pain to do. If I&#8217;ve [&hellip;]<\/p>\n","protected":false},"author":206,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[477,289,137],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/posts\/194"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/users\/206"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/comments?post=194"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/posts\/194\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/media?parent=194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/categories?post=194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/sfink\/wp-json\/wp\/v2\/tags?post=194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}