Size: 19
Comment:
|
Size: 8480
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
{{{{#!java | 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: 0. Initialize SVNKit to work with file:/// protocol. 1. Create a repository. 2. Populate it with some tree. 3. Make a copy of that tree: /A to /A_copy. 4. Checkout the entire repository tree to a working copy. 5. Make some changes to trunk (A). Commit those changes to the repository. 6. Then merge the changes from trunk (A) to the branch (A_copy). 7. Then again make some changes to trunk and commit them to the repository. 8. Again, merge the changes from trunk (A) to the branch (A_copy). This steps are reflected in code comments: |
Line 3: | Line 15: |
{{{#!java /* * ==================================================================== * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.examples.wc; import java.io.File; import java.io.IOException; import java.util.Collections; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNCommitClient; import org.tmatesoft.svn.core.wc.SVNCopyClient; import org.tmatesoft.svn.core.wc.SVNCopySource; import org.tmatesoft.svn.core.wc.SVNDiffClient; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNRevisionRange; import org.tmatesoft.svn.core.wc.SVNWCClient; /** * @version 1.2.0 * @author TMate Software Ltd. */ public class Merge { /** * Pass the absolute path of the base directory where all example data will be created in * arg[0]. The sample will create: * * - arg[0]/exampleRepository - repository with some test data * - arg[0]/exampleWC - working copy checked out from exampleRepository */ public static void main (String[] args) { //0. initialize SVNKit to work through file:/// protocol SamplesUtility.initializeFSFSprotocol(); File baseDirectory = new File(args[0]); File reposRoot = new File(baseDirectory, "exampleRepository"); File wcRoot = new File(baseDirectory, "exampleWC"); try { //1. first create a repository SamplesUtility.createRepository(reposRoot); //2. fill it with data SVNCommitInfo info = SamplesUtility.createRepositoryTree(reposRoot); //print out new revision info System.out.println(info); SVNClientManager clientManager = SVNClientManager.newInstance(); SVNURL reposURL = SVNURL.fromFile(reposRoot); //3. copy A to A_copy in the repository (url-to-url copy) SVNCopyClient copyClient = clientManager.getCopyClient(); SVNURL A_URL = reposURL.appendPath("A", true); SVNURL copyTargetURL = reposURL.appendPath("A_copy", true); SVNCopySource copySource = new SVNCopySource(SVNRevision.UNDEFINED, SVNRevision.HEAD, A_URL); info = copyClient.doCopy(new SVNCopySource[] { copySource }, copyTargetURL, false, false, true, "copy A to A_copy", null); //print out new revision info System.out.println(info); //4. checkout the entire repository tree SamplesUtility.checkOutWorkingCopy(reposURL, wcRoot); //5. now make some changes to the A tree and commit them SamplesUtility.writeToFile(new File(wcRoot, "iota"), "New text appended to 'iota'", true); SamplesUtility.writeToFile(new File(wcRoot, "A/mu"), "New text in 'mu'", false); SVNWCClient wcClient = SVNClientManager.newInstance().getWCClient(); wcClient.doSetProperty(new File(wcRoot, "A/B"), "spam", SVNPropertyValue.create("egg"), false, SVNDepth.EMPTY, null, null); //commit local changes SVNCommitClient commitClient = clientManager.getCommitClient(); commitClient.doCommit(new File[] { wcRoot }, false, "committing changes", null, null, false, false, SVNDepth.INFINITY); //6. now merge changes from trunk to the branch. SVNDiffClient diffClient = clientManager.getDiffClient(); SVNRevisionRange rangeToMerge = new SVNRevisionRange(SVNRevision.create(1), SVNRevision.HEAD); diffClient.doMerge(A_URL, SVNRevision.HEAD, Collections.singleton(rangeToMerge), new File(wcRoot, "A_copy"), SVNDepth.INFINITY, true, false, false, false); //7. now make some changes to the A tree again and commit them //change file contents of iota and A/D/gamma SamplesUtility.writeToFile(new File(wcRoot, "iota"), "New text2 appended to 'iota'", true); SamplesUtility.writeToFile(new File(wcRoot, "A/D/gamma"), "New text in 'gamma'", false); //remove A/C from version control wcClient.doDelete(new File(wcRoot, "A/C"), false, true, false); //commit local changes commitClient.doCommit(new File[] { wcRoot }, false, "committing changes again", null, null, false, false, SVNDepth.INFINITY); /* 8. do the same merge call, merge-tracking feature will merge only those revisions * which were not merged yet. */ diffClient.doMerge(A_URL, SVNRevision.HEAD, Collections.singleton(rangeToMerge), new File(wcRoot, "A_copy"), SVNDepth.INFINITY, true, false, false, false); } catch (SVNException svne) { System.out.println(svne.getErrorMessage()); System.exit(1); } catch (IOException ioe) { ioe.printStackTrace(); System.exit(1); } } } |
|
Line 4: | Line 141: |
Here are some comments on calling ''doMerge()'' in this example: * We use a pegged version of ''doMerge()'' which allows to merge differences between different revisions of the same file. * A_URL - URL of the merge source. * ''SVNRevision.HEAD'' - [[Peg revision|peg revision]] in which A_URL is valid for sure. * We use the entire revision range - from revisio 1 to HEAD not caring of how already merged revisions are skipped - merge-tracking feature will do that for us. * Then goes the merge target local path. * We use ''SVNDepth.INFINITY'' to recursively merge the whole target tree. * We want to merge only related (by history) objects, so the next parameter is ''true''. * We do not want our merge to delete any versioned files containing local edits or unversioned ones, so passing ''false''. * We do want a real merge to perform, not a just the final status of a potential merge, so passing ''false''. * We do wand a real merge to perform, not just to record mergeinfo without bringing real changes to A_copy. 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 }}} |
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:
Initialize SVNKit to work with file:/// protocol.
- Create a repository.
- Populate it with some tree.
- Make a copy of that tree: /A to /A_copy.
- Checkout the entire repository tree to a working copy.
- Make some changes to trunk (A). Commit those changes to the repository.
- Then merge the changes from trunk (A) to the branch (A_copy).
- Then again make some changes to trunk and commit them to the repository.
- 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, false, SVNDepth.INFINITY);
91
92 //6. now merge changes from trunk to the branch.
93 SVNDiffClient diffClient = clientManager.getDiffClient();
94 SVNRevisionRange rangeToMerge = new SVNRevisionRange(SVNRevision.create(1), SVNRevision.HEAD);
95
96 diffClient.doMerge(A_URL, SVNRevision.HEAD, Collections.singleton(rangeToMerge),
97 new File(wcRoot, "A_copy"), SVNDepth.INFINITY, true, false, false, false);
98
99
100 //7. now make some changes to the A tree again and commit them
101 //change file contents of iota and A/D/gamma
102 SamplesUtility.writeToFile(new File(wcRoot, "iota"), "New text2 appended to 'iota'", true);
103 SamplesUtility.writeToFile(new File(wcRoot, "A/D/gamma"), "New text in 'gamma'", false);
104 //remove A/C from version control
105 wcClient.doDelete(new File(wcRoot, "A/C"), false, true, false);
106
107 //commit local changes
108 commitClient.doCommit(new File[] { wcRoot }, false, "committing changes again", null, null, false, false, SVNDepth.INFINITY);
109
110 /* 8. do the same merge call, merge-tracking feature will merge only those revisions
111 * which were not merged yet.
112 */
113 diffClient.doMerge(A_URL, SVNRevision.HEAD, Collections.singleton(rangeToMerge),
114 new File(wcRoot, "A_copy"), SVNDepth.INFINITY, true, false, false, false);
115
116 } catch (SVNException svne) {
117 System.out.println(svne.getErrorMessage());
118 System.exit(1);
119 } catch (IOException ioe) {
120 ioe.printStackTrace();
121 System.exit(1);
122 }
123 }
124 }
Here are some comments on calling doMerge() in this example:
We use a pegged version of doMerge() which allows to merge differences between different revisions of the same file.
- A_URL - URL of the merge source.
SVNRevision.HEAD - peg revision in which A_URL is valid for sure.
- We use the entire revision range - from revisio 1 to HEAD not caring of how already merged revisions are skipped - merge-tracking feature will do that for us.
- Then goes the merge target local path.
We use SVNDepth.INFINITY to recursively merge the whole target tree.
We want to merge only related (by history) objects, so the next parameter is true.
We do not want our merge to delete any versioned files containing local edits or unversioned ones, so passing false.
We do want a real merge to perform, not a just the final status of a potential merge, so passing false.
- We do wand a real merge to perform, not just to record mergeinfo without bringing real changes to A_copy.
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