Performing 'svn merge URL_TO_TRUNK BRANCH_WC' with SVNKit

This example demonstrates how you can merge changes from trunk to a branch several times without specifying revisions. What we are going to do here is the following:

  1. Initialize SVNKit to work with file:/// protocol.

  2. Create a repository.
  3. Then populate it with a greek tree not using file system directories and files. All this initializing work is done with the help of the utility class called SamplesUtility.

  4. Make a copy of that tree: /A to /A_copy.
  5. Checkout the entire repository tree to a working copy.
  6. Make some changes to trunk (A). Commit those changes to the repository.
  7. Then merge the changes from trunk (A) to the branch (A_copy).
  8. Then again make some changes to trunk and commit them to the repository.
  9. Again, merge the changes from trunk (A) to the branch (A_copy).

This steps are reflected in code comments:

   1 /*
   2  * ====================================================================
   3  * Copyright (c) 2004-2008 TMate Software Ltd.  All rights reserved.
   4  *
   5  * This software is licensed as described in the file COPYING, which
   6  * you should have received as part of this distribution.  The terms
   7  * are also available at http://svnkit.com/license.html.
   8  * If newer versions of this license are posted there, you may use a
   9  * newer version instead, at your option.
  10  * ====================================================================
  11  */
  12 package org.tmatesoft.svn.examples.wc;
  13 
  14 import java.io.File;
  15 import java.io.IOException;
  16 import java.util.Collections;
  17 
  18 import org.tmatesoft.svn.core.SVNCommitInfo;
  19 import org.tmatesoft.svn.core.SVNDepth;
  20 import org.tmatesoft.svn.core.SVNException;
  21 import org.tmatesoft.svn.core.SVNPropertyValue;
  22 import org.tmatesoft.svn.core.SVNURL;
  23 import org.tmatesoft.svn.core.wc.SVNClientManager;
  24 import org.tmatesoft.svn.core.wc.SVNCommitClient;
  25 import org.tmatesoft.svn.core.wc.SVNCopyClient;
  26 import org.tmatesoft.svn.core.wc.SVNCopySource;
  27 import org.tmatesoft.svn.core.wc.SVNDiffClient;
  28 import org.tmatesoft.svn.core.wc.SVNRevision;
  29 import org.tmatesoft.svn.core.wc.SVNRevisionRange;
  30 import org.tmatesoft.svn.core.wc.SVNWCClient;
  31 
  32 
  33 /**
  34  * @version 1.2.0
  35  * @author  TMate Software Ltd.
  36  */
  37 public class Merge {
  38 
  39     /**
  40      * Pass the absolute path of the base directory where all example data will be created in 
  41      * arg[0]. The sample will create:
  42      *  
  43      *  - arg[0]/exampleRepository - repository with some test data
  44      *  - arg[0]/exampleWC         - working copy checked out from exampleRepository
  45      */
  46     public static void main (String[] args) {
  47         //0. initialize SVNKit to work through file:/// protocol
  48         SamplesUtility.initializeFSFSprotocol();
  49         
  50         File baseDirectory = new File(args[0]);
  51         File reposRoot = new File(baseDirectory, "exampleRepository");
  52         File wcRoot = new File(baseDirectory, "exampleWC");
  53         
  54         try {
  55             //1. first create a repository
  56             SamplesUtility.createRepository(reposRoot);
  57             //2. fill it with data
  58             SVNCommitInfo info = SamplesUtility.createRepositoryTree(reposRoot);
  59             //print out new revision info
  60             System.out.println(info);
  61 
  62             SVNClientManager clientManager = SVNClientManager.newInstance();
  63             
  64             SVNURL reposURL = SVNURL.fromFile(reposRoot);
  65 
  66             //3. copy A to A_copy in the repository (url-to-url copy)
  67             SVNCopyClient copyClient = clientManager.getCopyClient();
  68             SVNURL A_URL = reposURL.appendPath("A", true);
  69             SVNURL copyTargetURL = reposURL.appendPath("A_copy", true);
  70             SVNCopySource copySource = new SVNCopySource(SVNRevision.UNDEFINED, SVNRevision.HEAD, A_URL); 
  71             info = copyClient.doCopy(new SVNCopySource[] { copySource }, copyTargetURL, false, false, true, 
  72                     "copy A to A_copy", null);
  73             //print out new revision info
  74             System.out.println(info);
  75             
  76             //4. checkout the entire repository tree
  77             SamplesUtility.checkOutWorkingCopy(reposURL, wcRoot);
  78 
  79             
  80             //5. now make some changes to the A tree and commit them
  81             SamplesUtility.writeToFile(new File(wcRoot, "iota"), "New text appended to 'iota'", true);
  82             SamplesUtility.writeToFile(new File(wcRoot, "A/mu"), "New text in 'mu'", false);
  83             
  84             SVNWCClient wcClient = SVNClientManager.newInstance().getWCClient();
  85             wcClient.doSetProperty(new File(wcRoot, "A/B"), "spam", SVNPropertyValue.create("egg"), false, 
  86                     SVNDepth.EMPTY, null, null);
  87 
  88             //commit local changes
  89             SVNCommitClient commitClient = clientManager.getCommitClient();
  90             commitClient.doCommit(new File[] { wcRoot }, false, "committing changes", null, null, false, 
  91                                   false, SVNDepth.INFINITY);
  92             
  93             //6. now merge changes from trunk to the branch.
  94             SVNDiffClient diffClient = clientManager.getDiffClient();
  95             SVNRevisionRange rangeToMerge = new SVNRevisionRange(SVNRevision.create(1), SVNRevision.HEAD);
  96             
  97             diffClient.doMerge(A_URL, SVNRevision.HEAD, Collections.singleton(rangeToMerge), 
  98                     new File(wcRoot, "A_copy"), SVNDepth.INFINITY, true, false, false, false);
  99             
 100             
 101             //7. now make some changes to the A tree again and commit them
 102             //change file contents of iota and A/D/gamma
 103             SamplesUtility.writeToFile(new File(wcRoot, "iota"), "New text2 appended to 'iota'", true);
 104             SamplesUtility.writeToFile(new File(wcRoot, "A/D/gamma"), "New text in 'gamma'", false);
 105             //remove A/C from version control
 106             wcClient.doDelete(new File(wcRoot, "A/C"), false, true, false);
 107 
 108             //commit local changes
 109             commitClient.doCommit(new File[] { wcRoot }, false, "committing changes again", null, null, 
 110                                   false, false, SVNDepth.INFINITY);
 111 
 112             /* 8. do the same merge call, merge-tracking feature will merge only those revisions
 113              * which were not merged yet.
 114              */ 
 115             diffClient.doMerge(A_URL, SVNRevision.HEAD, Collections.singleton(rangeToMerge), 
 116                     new File(wcRoot, "A_copy"), SVNDepth.INFINITY, true, false, false, false);
 117             
 118         } catch (SVNException svne) {
 119             System.out.println(svne.getErrorMessage());
 120             System.exit(1);
 121         } catch (IOException ioe) {
 122             ioe.printStackTrace();
 123             System.exit(1);
 124         }
 125     }
 126 }

Here are some comments on calling doMerge() in this example:

Each merge operation in this example is equivalent to the following command line client' command:

svn merge file:///home/alex/workspace/tmp/exampleRepository/A /home/alex/workspace/exampleWC/A_copy

After the first merge, if you run 'svn status' in the working copy you should see this report:

alex@UFO:~/workspace/tmp/exampleWC$ $JSVN_PATH stat
 M     A_copy
 M     A_copy/B
M      A_copy/mu

And 'svn pg svn:mergeinfo .' in A_copy gives:

alex@UFO:~/workspace/tmp/exampleWC/A_copy$ $JSVN_PATH pg svn:mergeinfo .
/A:2-3

After the second merge the status report will look like this:

alex@UFO:~/workspace/tmp/exampleWC$ $JSVN_PATH stat
 M     A_copy
D      A_copy/C
M      A_copy/D/gamma

and propget report like this:

alex@UFO:~/workspace/tmp/exampleWC/A_copy$ $JSVN_PATH pg svn:mergeinfo .
/A:2-4

Merging from trunk to a branch (last edited 2008-09-04 15:57:55 by 194)