<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 4, 2015 at 7:48 AM, Paul Eggleton <span dir="ltr">&lt;<a href="mailto:paul.eggleton@linux.intel.com" target="_blank">paul.eggleton@linux.intel.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div>On Monday 26 October 2015 10:29:24 Tzu-Jung Lee wrote:<br>
&gt; Hi Paul<br>
&gt;<br>
&gt; On Mon, Oct 26, 2015 at 2:20 AM, Paul Eggleton &lt;<br>
&gt;<br>
&gt; <a href="mailto:paul.eggleton@linux.intel.com" target="_blank">paul.eggleton@linux.intel.com</a>&gt; wrote:<br>
&gt; &gt; Hi Tzu-Jung,<br>
&gt; &gt;<br>
&gt; &gt; Thanks for the patch.<br>
&gt; &gt;<br>
&gt; &gt; On Wednesday 21 October 2015 23:06:45 Tzu-Jung Lee wrote:<br>
&gt; &gt; &gt; The sync command is similar to the extract command, except it<br>
&gt; &gt; &gt; fetches the sync&#39;ed and patched branch to an existing git repository.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; This enables users to keep track the upstream development while<br>
&gt; &gt; &gt; maintaining their own local git repository at the same time.<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; Signed-off-by: Tzu-Jung Lee &lt;<a href="mailto:roylee17@currantlabs.com" target="_blank">roylee17@currantlabs.com</a>&gt;<br>
&gt; &gt; &gt; ---<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;  scripts/lib/devtool/standard.py | 73<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +++++++++++++++++++++++++++++++---------- 1 file changed, 56<br>
&gt; &gt;<br>
&gt; &gt; insertions(+),<br>
&gt; &gt;<br>
&gt; &gt; &gt; 17 deletions(-)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; diff --git a/scripts/lib/devtool/standard.py<br>
&gt; &gt; &gt; b/scripts/lib/devtool/standard.py index 5d7e903..2c6b7b3 100644<br>
&gt; &gt; &gt; --- a/scripts/lib/devtool/standard.py<br>
&gt; &gt; &gt; +++ b/scripts/lib/devtool/standard.py<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; @@ -234,7 +234,29 @@ def extract(args, config, basepath, workspace):<br>
&gt; &gt; &gt;          return 1<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;      srctree = os.path.abspath(args.srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -    initial_rev = _extract_source(srctree, args.keep_temp, args.branch,<br>
&gt; &gt;<br>
&gt; &gt; rd)<br>
&gt; &gt;<br>
&gt; &gt; &gt; +    initial_rev = _extract_source(srctree, args.keep_temp, args.branch,<br>
&gt; &gt; &gt; False, rd)<br>
&gt; &gt; &gt; +    <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(&#39;Source tree extracted to %s&#39; % srctree)<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +    if initial_rev:<br>
&gt; &gt; &gt; +        return 0<br>
&gt; &gt; &gt; +    else:<br>
&gt; &gt; &gt; +        return 1<br>
&gt; &gt;<br>
&gt; &gt; Hmm, so your patch shows this check being added but it&#39;s there in master.<br>
&gt; &gt; Are<br>
&gt; &gt; you patching an older version?<br>
&gt;<br>
&gt; Not really, it was patched against the tip of master.<br>
&gt; But git is sometimes confused by the boundary of back-to-back similar<br>
&gt; functions.<br>
&gt; So that checks are actually belongs to &quot;def sync&quot;, which was copied from<br>
&gt; &quot;def extract&quot;<br>
&gt;<br>
&gt;     def extract<br>
&gt;         ...<br>
&gt; --------------------<br>
&gt;<br>
&gt; |      [checks]<br>
&gt; |<br>
&gt; |   def sync<br>
&gt; |<br>
&gt; |       ...<br>
&gt;<br>
&gt; --------------------<br>
&gt;        [checks]<br>
&gt;<br>
&gt; &gt; +def sync(args, config, basepath, workspace):<br>
&gt; &gt; &gt; +    &quot;&quot;&quot;Entry point for the devtool &#39;sync&#39; subcommand&quot;&quot;&quot;<br>
&gt; &gt; &gt; +    import bb<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +    tinfoil = _prep_extract_operation(config, basepath,<br>
&gt; &gt; &gt; args.recipename)<br>
&gt; &gt; &gt; +    if not tinfoil:<br>
&gt; &gt; &gt; +        # Error already shown<br>
&gt; &gt; &gt; +        return 1<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +    rd = parse_recipe(config, tinfoil, args.recipename, True)<br>
&gt; &gt; &gt; +    if not rd:<br>
&gt; &gt; &gt; +        return 1<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt; +    srctree = os.path.abspath(args.srctree)<br>
&gt; &gt; &gt; +    initial_rev = _extract_source(srctree, args.keep_temp, args.branch,<br>
&gt; &gt; &gt; True, rd) <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(&#39;Source tree extracted to %s&#39; % srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;      if initial_rev:<br>
&gt; &gt; &gt; @@ -289,7 +311,7 @@ def _prep_extract_operation(config, basepath,<br>
&gt; &gt; &gt; recipename): return tinfoil<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -def _extract_source(srctree, keep_temp, devbranch, d):<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +def _extract_source(srctree, keep_temp, devbranch, sync, d):<br>
&gt; &gt; &gt;      &quot;&quot;&quot;Extract sources of a recipe&quot;&quot;&quot;<br>
&gt; &gt; &gt;      import bb.event<br>
&gt; &gt; &gt;      import oe.recipeutils<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; @@ -308,21 +330,26 @@ def _extract_source(srctree, keep_temp, devbranch,<br>
&gt; &gt;<br>
&gt; &gt; d):<br>
&gt; &gt; &gt;      _check_compatible_recipe(pn, d)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -    if os.path.exists(srctree):<br>
&gt; &gt; &gt; -        if not os.path.isdir(srctree):<br>
&gt; &gt; &gt; -            raise DevtoolError(&quot;output path %s exists and is not a<br>
&gt; &gt; &gt; directory&quot; % -                               srctree)<br>
&gt; &gt; &gt; -        elif os.listdir(srctree):<br>
&gt; &gt; &gt; -            raise DevtoolError(&quot;output path %s already exists and is &quot;<br>
&gt; &gt; &gt; -                               &quot;non-empty&quot; % srctree)<br>
&gt; &gt; &gt; +    if sync:<br>
&gt; &gt; &gt; +        if not os.path.exists(srctree):<br>
&gt; &gt; &gt; +                raise DevtoolError(&quot;output path %s does not exist&quot; %<br>
&gt; &gt; &gt; srctree) +    else:<br>
&gt; &gt; &gt; +        if os.path.exists(srctree):<br>
&gt; &gt; &gt; +            if not os.path.isdir(srctree):<br>
&gt; &gt; &gt; +                raise DevtoolError(&quot;output path %s exists and is not a<br>
&gt; &gt; &gt; directory&quot; % +                                   srctree)<br>
&gt; &gt; &gt; +            elif os.listdir(srctree):<br>
&gt; &gt; &gt; +                raise DevtoolError(&quot;output path %s already exists and<br>
&gt; &gt;<br>
&gt; &gt; is &quot;<br>
&gt; &gt;<br>
&gt; &gt; &gt; +                                   &quot;non-empty&quot; % srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -    if &#39;noexec&#39; in (d.getVarFlags(&#39;do_unpack&#39;, False) or []):<br>
&gt; &gt; &gt; -        raise DevtoolError(&quot;The %s recipe has do_unpack disabled,<br>
&gt; &gt;<br>
&gt; &gt; unable to<br>
&gt; &gt;<br>
&gt; &gt; &gt; &quot; -                           &quot;extract source&quot; % pn)<br>
&gt; &gt; &gt; +        if &#39;noexec&#39; in (d.getVarFlags(&#39;do_unpack&#39;, False) or []):<br>
&gt; &gt; &gt; +            raise DevtoolError(&quot;The %s recipe has do_unpack disabled,<br>
&gt; &gt; &gt; unable to &quot; +                               &quot;extract source&quot; % pn)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -    # Prepare for shutil.move later on<br>
&gt; &gt; &gt; -    bb.utils.mkdirhier(srctree)<br>
&gt; &gt; &gt; -    os.rmdir(srctree)<br>
&gt; &gt; &gt; +    if not sync:<br>
&gt; &gt; &gt; +        # Prepare for shutil.move later on<br>
&gt; &gt; &gt; +        bb.utils.mkdirhier(srctree)<br>
&gt; &gt; &gt; +        os.rmdir(srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;      # We don&#39;t want notes to be printed, they are too verbose<br>
&gt; &gt; &gt;      origlevel = bb.logger.getEffectiveLevel()<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; @@ -431,8 +458,11 @@ def _extract_source(srctree, keep_temp, devbranch,<br>
&gt; &gt;<br>
&gt; &gt; d):<br>
&gt; &gt; &gt;              <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(&#39;Adding local source files to srctree...&#39;)<br>
&gt; &gt; &gt;              shutil.move(os.path.join(tempdir, &#39;oe-local-files&#39;),<br>
&gt; &gt;<br>
&gt; &gt; srcsubdir)<br>
&gt; &gt;<br>
&gt; &gt; &gt; +        if sync:<br>
&gt; &gt; &gt; +            bb.process.run(&#39;git fetch file://&#39; + srcsubdir + &#39; &#39; +<br>
&gt; &gt; &gt; devbranch + &#39;:&#39; + devbranch, cwd=srctree)<br>
&gt; &gt; &gt; +        else:<br>
&gt; &gt; &gt; +            shutil.move(srcsubdir, srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; -        shutil.move(srcsubdir, srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;      finally:<br>
&gt; &gt; &gt;          bb.logger.setLevel(origlevel)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; @@ -532,7 +562,7 @@ def modify(args, config, basepath, workspace):<br>
&gt; &gt; &gt;      commits = []<br>
&gt; &gt; &gt;      srctree = os.path.abspath(args.srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;      if args.extract:<br>
&gt; &gt; &gt; -        initial_rev = _extract_source(args.srctree, False, args.branch,<br>
&gt; &gt;<br>
&gt; &gt; rd)<br>
&gt; &gt;<br>
&gt; &gt; &gt; +        initial_rev = _extract_source(args.srctree, False, args.branch,<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; False, rd) if not initial_rev:<br>
&gt; &gt; &gt;              return 1<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;          <a href="http://logger.info" rel="noreferrer" target="_blank">logger.info</a>(&#39;Source tree extracted to %s&#39; % srctree)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; @@ -1107,6 +1137,15 @@ def register_commands(subparsers, context):<br>
&gt; &gt; &gt;      parser_extract.add_argument(&#39;--keep-temp&#39;, action=&quot;store_true&quot;,<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; help=&#39;Keep temporary directory (for debugging)&#39;)<br>
&gt; &gt; &gt; parser_extract.set_defaults(func=extract)<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; +    parser_sync = subparsers.add_parser(&#39;sync&#39;, help=&#39;Synchronize the<br>
&gt; &gt; &gt; source for an existing recipe&#39;, +<br>
&gt; &gt; &gt; description=&#39;Synchronize the source for an existing recipe&#39;, +<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; formatter_class=argparse.ArgumentDefaultsHelpFormatter) +<br>
&gt; &gt; &gt; parser_sync.add_argument(&#39;recipename&#39;, help=&#39;Name for recipe to sync the<br>
&gt; &gt; &gt; source for&#39;) +    parser_sync.add_argument(&#39;srctree&#39;, help=&#39;Path to<br>
&gt; &gt; &gt; where<br>
&gt; &gt; &gt; to sync the source tree&#39;) +    parser_sync.add_argument(&#39;--branch&#39;,<br>
&gt; &gt; &gt; &#39;-b&#39;,<br>
&gt; &gt; &gt; default=&quot;devtool&quot;, help=&#39;Name for development branch to checkout&#39;) +<br>
&gt; &gt; &gt; parser_sync.add_argument(&#39;--keep-temp&#39;, action=&quot;store_true&quot;, help=&#39;Keep<br>
&gt; &gt; &gt; temporary directory (for debugging)&#39;) +<br>
&gt; &gt; &gt; parser_sync.set_defaults(func=sync)<br>
&gt; &gt; &gt; +<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt;      parser_update_recipe = subparsers.add_parser(&#39;update-recipe&#39;,<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; help=&#39;Apply changes from external source tree to recipe&#39;,<br>
&gt; &gt; &gt; description=&#39;Applies changes from external source tree to a recipe<br>
&gt; &gt; &gt; (updating/adding/removing patches as necessary, or by updating SRCREV)&#39;)<br>
&gt; &gt; &gt; parser_update_recipe.add_argument(&#39;recipename&#39;, help=&#39;Name of recipe to<br>
&gt; &gt; &gt; update&#39;)<br>
&gt; &gt;<br>
&gt; &gt; Exploring the use case a bit more, do you anticipate using this sync<br>
&gt; &gt; command<br>
&gt; &gt; in conjunction with a recipe that&#39;s in the workspace, or standalone?<br>
&gt;<br>
&gt; The use case is for workspace to keep git repos up-to-date. (Kind of<br>
&gt; rebasing) So the assumption is that the recipes have a corresponding git<br>
&gt; repository already, which could be an existing internal one, or a freshly<br>
&gt; constructed by an earlier devtool modify/extract. For standalone recipes,<br>
&gt; they can still go through the workspace :-)<br>
<br>
</div></div>I guess what I was wondering was is there a way we can better fit this in with<br>
devtool&#39;s workflow for when the recipe is in the workspace. However, other than<br>
perhaps not expecting the path to the source tree when the recipe is in the<br>
workspace I can&#39;t think of anything though. I guess we can always improve it<br>
later.<br></blockquote><div><br></div><div>Maybe we can fit it like the following:</div><div><br></div><div>1. Start to modify a recipe by either:</div><div><br></div><div>     a. reusing an existing &lt;srctree&gt;</div><div><br></div><div>        $ devtool modify &lt;recipename&gt; &lt;srctree&gt;</div><div><br></div><div>     b. or creating a new one with the -x option</div><div><br></div><div>        $ devtool modify &lt;recipename&gt; -x &lt;srctree&gt;</div><div><br></div><div>2. Work on the &lt;srctree&gt; </div><div><br></div><div>3. After a while, the upstream of &lt;recipename&gt; moves forward before we contribute our changes back.</div><div><br></div><div>4. Sync up the upstream changes into &lt;srctree&gt; with a new branch &lt;branchname&gt;</div><div><br></div><div>     $ devtool sync &lt;recipename&gt; &lt;srctree&gt; --branch &lt;branchname&gt;</div><div><br></div><div>5. Rebase our working branch onto the tip of the upstream &lt;branchname&gt; </div><div><br></div><div>    $ git rebase &lt;branchname&gt; devtool</div><div><br></div><div>[ Repeat 2 - 5 ]</div><div><br></div><div>6. Apply the changes back to the recipe.</div><div><br></div><div>    $ devtool update-recipe &lt;branchname&gt;</div><div><br></div><div>- Roy</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Acked-by: Paul Eggleton &lt;<a href="mailto:paul.eggleton@linux.intel.com" target="_blank">paul.eggleton@linux.intel.com</a>&gt;<br>
<div><div><br>
Cheers,<br>
Paul<br>
<br>
--<br>
<br>
Paul Eggleton<br>
Intel Open Source Technology Centre<br>
</div></div></blockquote></div><br></div></div>