Riff Blog - Music, sort of. And computing. And ... https://blog.riff.org/ en Tip of the day: patching legacy Drupal 7 projects with Composer https://blog.riff.org/2021_01_26_tip_of_the_day_patching_legacy_drupal_7_projects_with_composer <span class="field field--name-title field--type-string field--label-hidden">Tip of the day: patching legacy Drupal 7 projects with Composer</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Tue, 2021-01-26 10:30</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing/php_0" hreflang="en">PHP</a></div> <div class="field__item"><a href="/category/drupal_tips_and_tricks" hreflang="en">Drupal tips and tricks</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/tags/drupal7" hreflang="en">DRUPAL-7</a></li> <li><a href="/tags/composer" hreflang="en">Composer</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Some late Drupal 7 projects use Composer for project structure and tooling, even though they don't use Composer for the Drupal requirements proper. In that case, the normal Drupal 8/9 patching process using <a href="https://github.com/cweagans/composer-patches">cweagans/composer-patches</a> is not available, since dependencies are not handled with Composer. So is there a way to apply patches cleanly from Composer ? Sure there is! Let's see how.</p><!--break--> <h3>The problem</h3> <p>A typical situation happens like this:</p> <ol> <li>Legacy Drupal 7 project keeps on being used, but not upgraded to Drupal 8 / Drupal 9 or BackdropCMS/li> <li>Since it has to be maintainable, it is best on the then-current technique of git submodules, with each contrib being brought in as a separate submodule</li> <li>But then, more recent updates bring in Composer, e.g. to start using modern PHP components, starting the autoloader from <code>settings.local.php</code>; or using it for additional tools like Drush or PHPunit. </li> <li>When a module needs to be patched, the legacy drush-based process becomes an issue with submodules and Composer, and yet, because components are not downloaded by Composer, using <code>cweagans/composer-patches</code> is not an options</li> </ol> <p>Now, how can the patch process be handled in <code>composer.json</code>, just as is would be in any modern Composer deployment ?</p> <h3>How to use Composer patches with zero plugin</h3> <p>There is actually a very simple mechanism for this: using Composer hooks on <a href="https://getcomposer.org/doc/articles/scripts.md#command-events">command events</a>.</p> <p>That's all we need. Let's take an example: how to add the PHP 7.4 compatibility patch for Gmap, available on the <a href="https://www.drupal.org/project/gmap/issues/3118279">https://www.drupal.org/project/gmap/issues/3118279</a> issue ?</p> <h4>First step: creating a <code>composer patch</code> command</h4> <p>First we need to defined our patches and how to apply them. Here is what needs to be added to <code>composer.json</code> for a start:</p> <pre><div class="codeblock nowrap-expand"><code>{<br />&nbsp; ...misc sections...<br />&nbsp; &quot;require&quot;: { ... },<br />&nbsp; &quot;require-dev: { ... },<br />&nbsp; &quot;scripts&quot;: {<br />&nbsp;&nbsp;&nbsp; &quot;patch&quot;: [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;cd www/sites/all/modules/contrib/gmap; curl https://www.drupal.org/files/issues/2020-03-06/3118279-3.patch | patch -p1&quot;<br />&nbsp;&nbsp;&nbsp; ],<br />&nbsp; },<br />&nbsp; &quot;type&quot;: &quot;project&quot;<br />}</code></div></pre> <ul> <li>The <code>scripts</code> section allows adding custom commands to Composer</li> <li>In this case, we add a new <code>patch</code> command, to apply all patches</li> <li>Since commands can be just shell scripts, we create one line for each patch, made of two parts:<ul> <li><code>cd (the module directory)</code></li> <li>apply the patch straight from its download URL, taking advantage of the fact that the <code>patch</code> command takes patches form its standard input</li> </ul></li> <li>These two have to be kept as a single shell command, because the working directory is only retained for the direction of the shell subprocess, hence the <code>;</code></li> <li>With just that </li> </ul> At this step, we can now use <code>composer patch</code> to apply our patches on demand. But we can do better: apply the command automatically. <h4>Second step: applying patches on composer install/update</h4> <p>Remember, Composer includes these command hooks for install and update. To quote the Composer documentation:</p> <ul> <li><code>post-install-cmd</code>: occurs after the install command has been executed with a lock file present.</li> <li><code>post-update-cmd</code>: occurs after the update command has been executed, or after the install command has been executed without a lock file present.</li> </ul> <p>Beyond invoking shell scripts, Composer can also invoke its custom commands by prepending them with an <code>@</code> like Symfony services</p> <pre><div class="codeblock nowrap-expand"><code>&nbsp; &quot;scripts&quot;: {<br />&nbsp;&nbsp;&nbsp; &quot;patch&quot;: [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;cd www/sites/all/modules/contrib/gmap; curl https://www.drupal.org/files/issues/2020-03-06/3118279-3.patch | patch -p1&quot;<br />&nbsp;&nbsp;&nbsp; ],<br />&nbsp;&nbsp;&nbsp; &quot;post-install-cmd&quot;: [&quot;@patch&quot;],<br />&nbsp;&nbsp;&nbsp; &quot;post-update-cmd&quot;: [&quot;@patch&quot;]<br />&nbsp; },</code></div></pre> <p>Now, any time we run <code>composer install</code> or <code>composer update</code>, Composer will apply the patches without having to type <code>composer patch</code> manually.</p> <p>However, there are still two issues, which is especially annoying if the site uses submodules, but would also apply if all code is committed to the project:</p> <ul> <li>After one of <code>composer install</code> or <code>composer update</code>, the files are patches. So any subsequent install or update will find them modified, and attempt to preserve them or rollback, requiring many interactions</li> <li>The modified files are visible to git, which could invite us to commit them, which is probably not desired.</li> </ul> <h4>Third step: cleaning up</h4> <p>So we can just add an automatic cleanup <em>before</em> the install/update commands, so that our patch command, which runs <em>after</em> these tasks, will find the git checkout pristine</p> <p>For projects committing contrib dependencies, a simple <code>git reset --hard</code> is all it takes, but that will not work with submodules, so we need to be a bit smarter:</p> <pre><div class="codeblock nowrap-expand"><code>&nbsp; &quot;scripts&quot;: {<br />&nbsp;&nbsp;&nbsp; &quot;patch&quot;: [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;cd www/sites/all/modules/contrib/gmap; curl https://www.drupal.org/files/issues/2020-03-06/3118279-3.patch | patch -p1&quot;<br />&nbsp;&nbsp;&nbsp; ],<br />&nbsp;&nbsp;&nbsp; &quot;subclean&quot;: [&quot;git submodule update --init -f&quot;],<br />&nbsp;&nbsp;&nbsp; &quot;pre-install-cmd&quot;: [&quot;@subclean&quot;],<br />&nbsp;&nbsp;&nbsp; &quot;pre-update-cmd&quot;: [&quot;@subclean&quot;],<br />&nbsp;&nbsp;&nbsp; &quot;post-install-cmd&quot;: [&quot;@patch&quot;],<br />&nbsp;&nbsp;&nbsp; &quot;post-update-cmd&quot;: [&quot;@patch&quot;]<br />&nbsp; },</code></div></pre> <p>This time we define a <code>composer subclean</code> command to clean up submodules, and we register it to run before both install and update.</p> <p>Now, we can run <code>composer install</code> and <code>composer update</code> multiple times, and find the project clean everytime.</p> <p>Finally, come commit time, we can just run <code>composer subclean</code> before committing, or even as a git pre-commit hook, and the patch-induced changes in our contributions will be reset, at no risk of getting committed.</p> </div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Tue, 26 Jan 2021 09:30:58 +0000 Frederic Marand 353 at https://blog.riff.org https://blog.riff.org/2021_01_26_tip_of_the_day_patching_legacy_drupal_7_projects_with_composer#comments Error handling in Go 1.14 (french) https://blog.riff.org/2020_02_27_error_handling_in_go_1_14 <span class="field field--name-title field--type-string field--label-hidden">Error handling in Go 1.14 (french)</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Thu, 2020-02-27 08:33</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing/golang" hreflang="en">Google Go = Golang</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/taxonomy/term/245" hreflang="en">Golang Paris</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>La gestion des erreurs a été beaucoup enrichie en Go 1.13 et ses améliorations ont commencé à être appliquées en Go 1.14.</p> <p>Cette présentation, donnée au meetup Golang Paris chez Deezer le 26/02/2020 présente les mécanismes standard <code>error</code>, les tentatives d'évolution <code>check / handle</code> et <code>try / defer</code>, et le mécanisme d'<em>error wrapping</em> finalement validé depuis Go 1.13.</p> <script async class="speakerdeck-embed" data-id="ca1b83e7e72240a39b2748b029235f0b" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script></div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Thu, 27 Feb 2020 07:33:23 +0000 Frederic Marand 352 at https://blog.riff.org https://blog.riff.org/2020_02_27_error_handling_in_go_1_14#comments Showcase: Migrating FranceTVSport.fr to Drupal 8 and Symfony 4 https://blog.riff.org/2019_03_18_showcase_migrating_francetvsportfr_to_drupal_8_and_symfony_4 <span class="field field--name-title field--type-string field--label-hidden">Showcase: Migrating FranceTVSport.fr to Drupal 8 and Symfony 4</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Mon, 2019-03-18 14:03</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing/php_0" hreflang="en">PHP</a></div> <div class="field__item"><a href="/topic/computing/grokking_drupal" hreflang="en">Grokking Drupal</a></div> <div class="field__item"><a href="/topic/computing/php/symfony2" hreflang="en">Symfony</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/tags/drupal8" hreflang="en">DRUPAL-8</a></li> <li><a href="/tags/symfony" hreflang="en">Symfony</a></li> <li><a href="/taxonomy/term/243" hreflang="en">DrupalCamp</a></li> <li><a href="/taxonomy/term/244" hreflang="en">Showcase</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>The opening talk as <a href="https://paris2019.drupal.fr/">DrupalCamp Paris 2019</a> was a presentation given by Thomas Jolliet (FranceTV) and yours truly about how we rebuilt <a href="https://sport.francetvinfo.fr/">FranceTV Sport</a> to a Symfony 4 / headless Drupal 8 combo.</p> <p>The most salient points of the talk are probably the "defense in depth" mechanisms we built for scalability and fault tolerance, and the business results, like -85% full page load time, -65% <a href="https://sites.google.com/a/webpagetest.org/docs/using-webpagetest/metrics/speed-index">speed index</a>, or +50% iOS app traffic.</p><!--break--> <script async class="speakerdeck-embed" data-id="8be5e630ce5f480986369fad3c1a180f" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script></div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Mon, 18 Mar 2019 13:03:18 +0000 Frederic Marand 351 at https://blog.riff.org https://blog.riff.org/2019_03_18_showcase_migrating_francetvsportfr_to_drupal_8_and_symfony_4#comments Go internals unofficial wiki restored https://blog.riff.org/2019_03_04_go_internals_unofficial_wiki_restored <span class="field field--name-title field--type-string field--label-hidden">Go internals unofficial wiki restored</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Mon, 2019-03-04 12:09</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing/golang" hreflang="en">Google Go = Golang</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/tags/google" hreflang="en">google</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>The "Go internals unofficial wiki" on goin.wikispot.org used to be a valuable resource for developers interesting in the internal operation of the Go runtime, but disappeared when wikispot.org went down in 04/2014.</p> <p>I spent a couple of hours this morning to restore and reformat its contents to the <a href="https://wiki.audean.com/go/internals">Golang section on the Audean wiki</a>.</p> <p>Enjoy... but responsibly : its content was fresh in 2014, not last week... </p></div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Mon, 04 Mar 2019 11:09:22 +0000 Frederic Marand 350 at https://blog.riff.org https://blog.riff.org/2019_03_04_go_internals_unofficial_wiki_restored#comments GoLand tip of the day: clean up GoLand leftover cache and log folders https://blog.riff.org/2018_12_08_goland_tip_of_the_day_clean_up_goland_leftover_cache_and_log_folders <span class="field field--name-title field--type-string field--label-hidden">GoLand tip of the day: clean up GoLand leftover cache and log folders</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sat, 2018-12-08 17:10</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing/golang" hreflang="en">Google Go = Golang</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/taxonomy/term/242" hreflang="en">Goland</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>When GoLand is upgraded from one version to the next, the deployment process adds a new set of configuration, cache, and log directories. But it does not remove the versions associated to the previous versions of the IDE, to ease rolling back to the previous version if an upgrade happens to cause an issue.</p> <p>So after some time, removing these now-unused folders will regain some disk space, possibly more than 1 GB. Here are their respective locations and content on macOS:</p><!--break--> <table> <thead> <tr> <th scope="col">Role</th> <th scope="col">Size indication</th> <th scope="col">Configuration variable</th> <th scope="col">Default location</th> </tr> </thead> <tbody> <tr> <th scope="row">Configuration</th> <td>3 to 10 MB</td> <td><code>idea.config.path</code></td> <td> <ul> <li>~/Library/Preferences/Gogland1.0</li> <li>~/Library/Preferences/Goland.(version)</li> </ul> </td> </tr> <tr> <th scope="row">Plugins</th> <td>50 to 100 MB</td> <td><code>idea.plugins.path</code></td> </td> <td> <ul> <li>~/Library/Application Support/Gogland1.0</li> <li>~/Library/Application Support/GoLand-EAP</li> <li>~/Library/Application Support/GoLand</li> <li>~/Library/Application Support/GoLand.(version)</li> </ul> </tr> <tr> <th scope="row">Caches</th> <td>200 MB or (much) more</td> <td><code>idea.system.path</code></td> <td> <ul> <li>~/Library/Caches/Gogland1.0</li> <li>~/Library/Caches/GoLand2018.(version)</li> </ul> </td> </tr> <tr> <th scope="row">Logs</th> <td>1 to 10 MB</td> <td><code>idea.log.path</code></td> <td> <ul> <li>~/Library/Logs/Gogland1.0</li> <li>~/Library/Logs/GoLand2018.(version)</li> </ul> </td> </tr> </tbody> </table> <p>On Windows and Linux, lookup the location using the name of the configuration variable in the third column.</p> <p>Notice that the Toolbox app uses similar locations</p></div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Sat, 08 Dec 2018 16:10:28 +0000 Frederic Marand 349 at https://blog.riff.org https://blog.riff.org/2018_12_08_goland_tip_of_the_day_clean_up_goland_leftover_cache_and_log_folders#comments GoLand tip of the day: when Make run configurations don't find go https://blog.riff.org/2018_10_12_goland_tip_of_the_day_when_make_run_configurations_dont_find_go <span class="field field--name-title field--type-string field--label-hidden">GoLand tip of the day: when Make run configurations don&#039;t find go</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Fri, 2018-10-12 13:31</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing" hreflang="en">Computing</a></div> <div class="field__item"><a href="/topic/computing/golang" hreflang="en">Google Go = Golang</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/taxonomy/term/242" hreflang="en">Goland</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h3>The problem</h3> In a GoLand 2018.3 EAP run configuration, a Makefile run configuration finds the <code>go</code> binary on macOS, but not on Ubuntu, causing make targets like this one to fail: <pre><div class="codeblock nowrap-expand"><code>client/test.wasm: client/main.go<br /> # Building WASM<br /> GOARCH=wasm GOOS=js go build -o client/test.wasm client/main.go<br /><br />/usr/bin/make -f (some edited path)/Makefile client/test.wasm<br />/bin/sh: 1: go: not found<br />make: *** [client/test.wasm] Error 127</code></div></pre> <p>Simple enough to fix...</p><!--break--> <h3>The diagnostic</h3> <p>On the command line, the same <code>GOARCH=wasm GOOS=js go build -o client/test.wasm client/main.go</code> line works normally. Looks like a path issue in Goland or the plugin. Checking in the Makefile:</p> <pre><div class="codeblock nowrap-expand"><code>client/test.wasm: client/main.go<br /> # &quot;${PATH}&quot;<br /> # Building WASM<br /> GOARCH=wasm GOOS=js go build -o client/test.wasm client/main.go<br /><br /># Building WASM<br />make: *** [client/test.wasm] Error 127<br /># &quot;/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin&quot;</code></div></pre> <p>So inded, on at least this version, the PATH is not taken into account. Let's fix this.</p> <h3>The solution</h3> <p>Of course, one could just add the Go bin path to the tasks in these targets, but this is uncalled for on other environments, so we can just remind Goland to add this path to the run configuration.</p> <ol> <li>Edit the Run configuration</li> <li>Edit the <code>Environment variables</code> field</li> <li>Add a definition for the <code>PATH</code> variable taken from an <code>echo $PATH</code> on the command line</li> <li>Apply and close</li> </ol> <h3>Oddities</h3> As usual, Make has its own peculiar charm, requiring the variable name to use the braced format shown above instead of a plain <code>$PATH</code>. Trying to extend the PATH variable by just adding something like <code>$PATH:/usr/local/go/bin</code> or <code>${PATH}:/usr/local/go/bin</code> won't work: <ul> <li>in the first case, Make will receive the result of evaluation <code>$P</code>, then the <code>ATH</code> string, so other binaries beyond the ones in <code>/usr/local/go/bin</code> will be missing</li> <li>in the second case, Make detects a variable referencing itself and aborts the task</li> </ul> </div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Fri, 12 Oct 2018 11:31:06 +0000 Frederic Marand 347 at https://blog.riff.org https://blog.riff.org/2018_10_12_goland_tip_of_the_day_when_make_run_configurations_dont_find_go#comments Tip of the day: how to compare Guitar Pro files https://blog.riff.org/2018_10_07_tip_of_the_day_how_to_compare_guitar_pro_files <span class="field field--name-title field--type-string field--label-hidden">Tip of the day: how to compare Guitar Pro files</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sun, 2018-10-07 11:21</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/music" hreflang="en">Music</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/taxonomy/term/240" hreflang="en">GuitarPro</a></li> <li><a href="/taxonomy/term/241" hreflang="en">GP7</a></li> <li><a href="/tags/xml" hreflang="en">XML</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h2>The problem</h2> <p>When working on compositions in a multi-member band (currently 5 in <a href="https://www.facebook.com/AnotherDay78">AnotherDay</a>, each member tends to create their own Guitar Pro files to avoid overwriting the previous versions created by other band members. And <code>.gp</code> files tend to accumulate for the same song. At which point I start to wonder: "I know there's this riff in one of the versions, but which one ?" or "Are these two files really different or could I just merge them by editing a few notes, or remove one altogether ?"</p> <p>The problem, of course, is that <a href="https://www.guitar-pro.com/en/index.php?pg=guitar-pro">Guitar Pro</a>, even in version 7.5, has no builtin file comparison tool. How can one compare these files ?</p> <h2>Diagnostic</h2> <p>If GP7 doesn't have a buitin solution, how about comparing the files themselves ? Problem: the file format is not documented. But a <code>file score.gp</code> command returns <code>Zip archive data, at least v2.0 to extract</code>. So let's unzip the file to see what it looks like: <pre><div class="codeblock nowrap-expand"><code>$ unzip score.gp<br />Archive:&nbsp; score.gp<br />&nbsp;&nbsp; creating: Content/<br />&nbsp; inflating: Content/BinaryStylesheet<br />&nbsp; inflating: Content/LayoutConfiguration<br />&nbsp; inflating: Content/PartConfiguration<br />&nbsp; inflating: Content/Preferences.json<br />&nbsp; inflating: Content/score.gpif<br />&nbsp; inflating: VERSION<br />$ cat VERSION<br />7.0<br />$ cd Content<br />$ file *<br />BinaryStylesheet:&nbsp;&nbsp;&nbsp; data<br />LayoutConfiguration: X11 SNF font data, MSB first<br />PartConfiguration:&nbsp;&nbsp; data<br />Preferences.json:&nbsp;&nbsp;&nbsp; ASCII text, with no line terminators<br />score.gpif:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XML 1.0 document text, UTF-8 Unicode text, with very long lines<br />$</code></div></pre> A quick look at the content of the files confirms that the actual score data is contained in the <code>score.gpif</code> file. <pre><div class="codeblock nowrap-expand"><code>$ tidy -q -xml -indent score.gpif | head -20<br />&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br />&lt;GPIF&gt;<br />&nbsp; &lt;GPVersion&gt;7&lt;/GPVersion&gt;<br />&nbsp; &lt;GPRevision required=&quot;12021&quot; recommended=&quot;12023&quot;&gt;<br />&nbsp; 12024&lt;/GPRevision&gt;<br />&nbsp; &lt;Encoding&gt;<br />&nbsp;&nbsp;&nbsp; &lt;EncodingDescription&gt;GP7&lt;/EncodingDescription&gt;<br />&nbsp; &lt;/Encoding&gt;<br />&nbsp; &lt;Score&gt;<br />&nbsp;&nbsp;&nbsp; &lt;Title&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;![CDATA[]]&gt;<br />&lt;/Title&gt;<br />&nbsp;&nbsp;&nbsp; &lt;SubTitle&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;![CDATA[]]&gt;<br />&lt;/SubTitle&gt;<br />&nbsp;&nbsp;&nbsp; &lt;Artist&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;![CDATA[]]&gt;<br />&lt;/Artist&gt;<br />&nbsp;&nbsp;&nbsp; &lt;Album&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;![CDATA[]]&gt;<br />$</code></div></pre> Ahah... so it's an XML document with a <code>GPIF</code> top-level element. A quick search with that keyword lands us on a file called "The Guitarpro 7 (".GP") file format" by the <a href="https://musescore.org/">MuseScore</a> developers, currently available at <a href="https://musescore.org/sites/musescore.org/files/2017-08/the_guitarpro_7_file%20format.doc">https://musescore.org/sites/musescore.org/files/2017-08/the_guitarpro_7_file%20format.doc</a>. And its content allows one to understand the contents of these scores. I bet it would even come in handy to manually edit/repair a file corrupted by the frequent crashes of Guitar Pro.</p> <p>But that's not the goal for today, we can now compare these scores more or less easily.</p> <h2>The solutions</h2> <p>First solution is to use the process described above and compare the <code>score.gpif</code> files using your <a href="http://meldmerge.org/">favorite text comparison software</a>. Works well, but can we do it with less command-line manipulation ?</p> <p>Turns out, most of the process can be replicated in Guitar Pro itself, by using the new (?) MusicXML export: just navigate to <code>File</code> / <code>Export</code> / <code>MusicXML...</code> to export the scores to compare, and you directly get a pair of XML files which you can directly compare in your visual text comparison tool. Problem solved.</p> </div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Sun, 07 Oct 2018 09:21:56 +0000 Frederic Marand 346 at https://blog.riff.org https://blog.riff.org/2018_10_07_tip_of_the_day_how_to_compare_guitar_pro_files#comments Munin plugins for Beanstalkd in PHP are now 1.0.0 https://blog.riff.org/2018_08_12_munin_plugins_for_beanstalkd_in_php_are_now_100 <span class="field field--name-title field--type-string field--label-hidden">Munin plugins for Beanstalkd in PHP are now 1.0.0</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sun, 2018-08-12 21:16</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing/php_0" hreflang="en">PHP</a></div> <div class="field__item"><a href="/topic/computing/php/php_tips_and_tricks" hreflang="en">PHP Tips and tricks</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/taxonomy/term/238" hreflang="en">munin</a></li> <li><a href="/taxonomy/term/239" hreflang="en">observability</a></li> <li><a href="/tags/php_0" hreflang="en">php</a></li> <li><a href="/tags/phpfig" hreflang="en">php-fig</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>In 2014, I created a PHP version of the <a href="https://github.com/fgm/beanstalk-munin-php">Munin plugins for Beanstalkd</a> introduced by AirBnB, but originally created in Python.</p> <p>Fast forward four years, and after being adapted for compliances with the PHP-FIG PSR1, PSR2 and PSR12 standards, as well as the Zend coding standards, and with extra documentation, I published the first "stable" version 1.0.0 of the package today under the Apache APL-2.0 license.</p> <p>To use it and ensure observability of your <a href="http://kr.github.io/beanstalkd/">favorite job queue</a>, follow the instructions in the INSTALL.md file. In short, it's just 3 steps: </p> <ol> <li>clone the repository</li> <li>install its dependencies with <code>composer install</code></li> <li>symlink the plugins to <code>/etc/munin/plugins</code></li> </ol> <p>That's it, you can now plot command rate, connections, jobs rate, age in queue, queue size by type, and timeouts frequency.</p> </div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Sun, 12 Aug 2018 19:16:07 +0000 Frederic Marand 345 at https://blog.riff.org https://blog.riff.org/2018_08_12_munin_plugins_for_beanstalkd_in_php_are_now_100#comments Lighthouse 3.0 is out: Drupal 8.5 has killer performance https://blog.riff.org/2018_08_05_lighthouse_30_is_out_drupal_85_has_killer_performance <span class="field field--name-title field--type-string field--label-hidden">Lighthouse 3.0 is out: Drupal 8.5 has killer performance</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sun, 2018-08-05 18:08</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/topic/computing" hreflang="en">Computing</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/tags/drupal8" hreflang="en">DRUPAL-8</a></li> <li><a href="/tags/performance" hreflang="en">performance</a></li> <li><a href="/tags/chrome" hreflang="en">chrome</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>As you may have noticed if you are a regular here, I just refreshed the theme on this site to a custom theme built on Bartik. And since Chrome had just been updated, I took the newly updated performance audit.</p> <p><img src="/sites/default/files//2018-08/Drupal8-Lighthouse3-100.png" alt="Screenshot of a 100% score on Lighthouse 3.0 by Drupal 8.5" style="width: 100%" /></p> <p>What more to say ?</p></div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> </section> Sun, 05 Aug 2018 16:08:11 +0000 Frederic Marand 344 at https://blog.riff.org https://blog.riff.org/2018_08_05_lighthouse_30_is_out_drupal_85_has_killer_performance#comments How to debug Drupal 8 Functional tests with XDebug https://blog.riff.org/2018_07_29_how_to_debug_drupal_8_functional_tests_with_xdebug <span class="field field--name-title field--type-string field--label-hidden">How to debug Drupal 8 Functional tests with XDebug</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/frederic_marand" typeof="schema:Person" property="schema:name" datatype="">Frederic Marand</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sun, 2018-07-29 21:12</span> <div class="field field--name-field-topic field--type-entity-reference field--label-hidden field__items"> <div class="field__item"><a href="/category/drupal_tips_and_tricks" hreflang="en">Drupal tips and tricks</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-hidden clearfix"> <ul class="links field__items"> <li><a href="/tags/xdebug" hreflang="en">xdebug</a></li> <li><a href="/tags/phpstorm" hreflang="en">phpstorm</a></li> <li><a href="/taxonomy/term/237" hreflang="en">phpunit</a></li> <li><a href="/tags/testing" hreflang="en">testing</a></li> <li><a href="/tags/drupal8" hreflang="en">DRUPAL-8</a></li> </ul> </div> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h3>The problem</h3> <p>While converting the old-style functional tests in the <a href="https://drupal.org/project/mongodb">MongoDB project</a> from <code>WebTestBase</code> to <code>BrowserTestBase</code>, I stumbled upon a problem: after following the drupal.org instructions to <a href="https://www.drupal.org/docs/8/phpunit/running-phpunit-tests-within-phpstorm">run PHPunit tests from PhpStorm</a>, doing step-by-step debugging in the IDE worked nicely, but then stopped at the first <code>$this-&gt;drupalLogin();</code> call, returning a 404 after a very long delay, although the same call running without debugging worked normally. What could be going on&nbsp;?</p><!--break--> <h3>The diagnostic</h3> <p>Stepping into <code>UiHelperTrait::drupalLogin()</code>, I noticed the delay occurent during the <code>drupalGet(&#039;user/login&#039;)</code> call early in the method, before submitting the account identification. Could it be the issue&nbsp;?</p> <p>Indeed, evaluating the result of the call via <code>$this-&gt;getSession()-&gt;getStatusCode();</code> after that call returned show a 504 Timeout HTTP status code. And indeed, dumping the page with <code>$this-&gt;getSession()-&gt;getPage()-&gt;getContent()</code> show it to contain a typically timeout page.</p> <p>Examining the logs showed the timeout happened at the PHP level, during the opposite direction call performed by Xdebug towards the debugging client, although such calls obviously worked since I'd been stepping through code for hours before that.</p> <h3>The solution</h3> <p>The solution was suggested by the always helpful and knowledgeable <a href="https://www.drupal.org/u/berdir">@berdir</a> : PhpStorm happens to set a limit to the number of simultaneous connections it will accept for debugging, and that limit is 1 by default.</p> <p>All of a sudden, it made sense: during classical debugging, the PHP interpreter from the host site establishes one connection to the client (the PhpStorm IDE), but when invoking the child site during such a call, a second instance of the interpreter is started and tries to connect too... but is blocked by the single connection limit of the default configuration.</p> <p><img alt="Screenshot from the XDebug preferences in PhpStorm 2018.1.2" data-entity-type="file" data-entity-uuid="7ed4529a-9d45-4f0d-a734-1eaf507a6aaa" src="/sites/default/files/inline-images/phpstorm-xdebug-connections_0.png" style="width: 50%; float: right; margin-left: 1em;" /> So all it takes is increase the number of connections!</p> <p>In PhpStorm 2018.1.2 for macOS, the settings can be found at <em>PhpStorm / Preferences / Languages &amp; Frameworks / PHP / Debug</em> in the <code>External connections</code> part of the right pane, as shown below.</p> <p>No need to restart the IDE or PHP, just restart the debugging run configuration, and it works beautifully.</p> </div> <section class="field field--name-comment-node-story field--type-comment field--label-hidden comment-wrapper"> <article role="article" data-comment-user-id="0" id="comment-5179" class="comment js-comment by-anonymous clearfix"> <span class="hidden" data-comment-timestamp="1533063873"></span> <footer class="comment__meta"> <article typeof="schema:Person" about="/user/0" class="profile"> </article> <p class="comment__author"><span lang="" typeof="schema:Person" property="schema:name" datatype="">ThisHosting.Rocks (not verified)</span></p> <p class="comment__time">Mon, 2018-07-30 23:49</p> <p class="comment__permalink"><a href="/comment/5179#comment-5179" hreflang="en">Permalink</a></p> </footer> <div class="comment__content"> <h3><a href="/comment/5179#comment-5179" class="permalink" rel="bookmark" hreflang="en">thanks</a></h3> <div class="clearfix text-formatted field field--name-comment-body field--type-text-long field--label-hidden field__item"><p>Just had to use XDebug and this came in handy. Thanks!</p> </div> <drupal-render-placeholder callback="comment.lazy_builders:renderLinks" arguments="0=5179&amp;1=default&amp;2=en&amp;3=" token="SQyO6PrbsB1PM9Fm6TQyTTySzMujtrEoucKtkGuHtSo"></drupal-render-placeholder> </div> </article> </section> Sun, 29 Jul 2018 19:12:18 +0000 Frederic Marand 343 at https://blog.riff.org https://blog.riff.org/2018_07_29_how_to_debug_drupal_8_functional_tests_with_xdebug#comments