{"id":981,"date":"2012-08-17T11:10:07","date_gmt":"2012-08-17T11:10:07","guid":{"rendered":"http:\/\/kera.name\/articles\/?p=981"},"modified":"2012-08-17T11:20:38","modified_gmt":"2012-08-17T11:20:38","slug":"why-caution-is-advised-when-svn-copying-directories","status":"publish","type":"post","link":"https:\/\/kera.name\/articles\/2012\/08\/why-caution-is-advised-when-svn-copying-directories\/","title":{"rendered":"Why Caution Is Advised When SVN Copying Directories"},"content":{"rendered":"<p><em><code>svn copy<\/code>&#039;s behaviour when copying directories to paths that already exist does not quite match that of Linux&#039;s <code>cp<\/code> command.<\/em><\/p>\n<hr \/>\n<p>This week at work we resumed development on a new software feature that we hadn&#039;t had time to look at since its initial proof-of-concept phase several months ago. We do feature development on feature-specific SVN branches, so the unfinished code was safely tucked away in its own pocket universe whilst we applied a whole ton of new functionality and API changes on the trunk in the meantime. Today it came time to update this branch so that its code was up-to-date and we could continue working.<\/p>\n<p>Now, we also have a couple of levels of dependencies linked in by SVN externals:<\/p>\n<pre><code>project\/trunk\n   \\\n    |- dep1\/trunk@SomeRecentRev\n    |- dep2\/trunk@SomeRecentRev<\/code><\/pre>\n<p>The proof-of-concept feature&#039;s project branch had a feature-specific branch for <code>dep1<\/code>, but not for <code>dep2<\/code>:<\/p>\n<pre><code>project\/branches\/thefeature\n   \\\n    |- dep1\/branches\/thefeature\n    |- dep2\/trunk@SomeOldRev<\/code><\/pre>\n<h3>How we caused a problem<\/h3>\n<p>Today, to clean things up and to obtain a full working environment for the new feature, we needed to create a branch for <code>dev2<\/code> as well. Using version 1.6.6 of the command-line client:<\/p>\n<pre><code>svn copy \\\n   https:\/\/repohost\/svn\/dep2\/trunk\/ \\\n   https:\/\/repohost\/svn\/dep2\/branches\/thefeature\/ \\\n   -m\"Created new branch for thefeature development\"<\/code><\/pre>\n<p>One would think that the result would be:<\/p>\n<pre><code>project\/branches\/thefeature\n   \\\n    |- dep1\/branches\/thefeature\n    |- dep2\/branches\/thefeature<\/code><\/pre>\n<p>and, well, it was.<\/p>\n<p>However, something went wrong. Having done this, upon building <code>project\/branches\/thefeature<\/code>, it became evident that the code under <code>dep2\/branches\/thefeature<\/code> was old. Really old. Probably from around <code>@SomeOldRev<\/code>, dating back to development on the original proof-of-concept. But didn&#039;t we just copy from the trunk <code>HEAD<\/code>? Sure we did&#8230;<\/p>\n<h3>Mystery solved<\/h3>\n<p>Closer inspection revealed that there was now an unexpected subdirectory &#034;trunk&#034; underneath this outdated code, which contained the expected recent code:<\/p>\n<pre><code>project\/branches\/thefeature\n   \\\n    |- dep1\/branches\/thefeature\n    |- dep2\/branches\/thefeature\n          \\\n           | old code\n           | \"trunk\/\"\n                 \\\n                  | new code<\/code><\/pre>\n<p>Where on Earth did this come from?<\/p>\n<p>Around this time it became known that there had in fact been an orphaned <code>dep2\/branches\/thefeature<\/code> already in existence from the days of <code>@SomeOldRev<\/code> that had never been used. Still, I&#039;d guessed that <code>svn copy<\/code>&#039;s mechanism would follow the convention of Linux <code>cp<\/code>, which when copying directories has significance in trailing slashes on the <em>source-dir<\/em>. That is, with <code>cp<\/code>, if the destination directory already exists and you do <em>not<\/em> use a trailing slash on the <em>source-dir<\/em>, then <a href=\"http:\/\/tomorrowisfriday.wordpress.com\/2008\/01\/09\/copying-a-directory-to-an-existing-directory-as-in-mv-the-trailing-slash-significance\/\">you are actually putting a copy of <em>source-dir<\/em> inside <em>dest-dir<\/em><\/a>. But our <code>svn copy<\/code> invocation used trailing slashes on both the source and destination arguments!<\/p>\n<p>Some chatter on the SVN mailing list included <a href=\"http:\/\/svn.haxx.se\/users\/archive-2007-04\/1035.shtml\">this<\/a>:<\/p>\n<blockquote>\n<p>I did a bit of research in the list archive, and came across this snippet,<br \/>\nposted by someone basically saying this was reasonable behaviour because<br \/>\nthat&#039;s how *nix does it:<\/p>\n<pre><code>cp path\/A path\/B --> if path\/B doesn't exist, creates path\/B\n                     if path\/B does    exist, creates path\/B\/A <\/code><\/pre>\n<\/blockquote>\n<p>with no mention of the trailing-slash rule. Indeed, from our experience, the above would seem to be the case <em>whether you include the trailing slash or not<\/em>.<\/p>\n<p>Nuking the entire <code>dep2\/branches\/thefeature<\/code> directory and re-copying from trunk solved all the build problems and left the directory structure as expected.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><code>svn copy<\/code>&#039;s behaviour when copying directories to paths that already exist does not quite match that of Linux&#039;s <code>cp<\/code> command.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[12,67],"_links":{"self":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/981"}],"collection":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/comments?post=981"}],"version-history":[{"count":8,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/981\/revisions"}],"predecessor-version":[{"id":990,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/posts\/981\/revisions\/990"}],"wp:attachment":[{"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/media?parent=981"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/categories?post=981"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kera.name\/articles\/wp-json\/wp\/v2\/tags?post=981"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}