Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
JazzDiffCommand |
|
| 4.5;4,5 |
1 | package org.apache.maven.scm.provider.jazz.command.diff; | |
2 | ||
3 | /* | |
4 | * Licensed to the Apache Software Foundation (ASF) under one | |
5 | * or more contributor license agreements. See the NOTICE file | |
6 | * distributed with this work for additional information | |
7 | * regarding copyright ownership. The ASF licenses this file | |
8 | * to you under the Apache License, Version 2.0 (the | |
9 | * "License"); you may not use this file except in compliance | |
10 | * with the License. You may obtain a copy of the License at | |
11 | * | |
12 | * http://www.apache.org/licenses/LICENSE-2.0 | |
13 | * | |
14 | * Unless required by applicable law or agreed to in writing, | |
15 | * software distributed under the License is distributed on an | |
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
17 | * KIND, either express or implied. See the License for the | |
18 | * specific language governing permissions and limitations | |
19 | * under the License. | |
20 | */ | |
21 | ||
22 | import org.apache.maven.scm.ScmException; | |
23 | import org.apache.maven.scm.ScmFile; | |
24 | import org.apache.maven.scm.ScmFileSet; | |
25 | import org.apache.maven.scm.ScmFileStatus; | |
26 | import org.apache.maven.scm.ScmVersion; | |
27 | import org.apache.maven.scm.command.diff.AbstractDiffCommand; | |
28 | import org.apache.maven.scm.command.diff.DiffScmResult; | |
29 | import org.apache.maven.scm.command.status.StatusScmResult; | |
30 | import org.apache.maven.scm.provider.ScmProviderRepository; | |
31 | import org.apache.maven.scm.provider.jazz.command.JazzConstants; | |
32 | import org.apache.maven.scm.provider.jazz.command.JazzScmCommand; | |
33 | import org.apache.maven.scm.provider.jazz.command.consumer.DebugLoggerConsumer; | |
34 | import org.apache.maven.scm.provider.jazz.command.consumer.ErrorConsumer; | |
35 | import org.apache.maven.scm.provider.jazz.command.status.JazzStatusCommand; | |
36 | ||
37 | import java.io.File; | |
38 | import java.util.HashMap; | |
39 | import java.util.Iterator; | |
40 | import java.util.List; | |
41 | import java.util.Map; | |
42 | ||
43 | // The Maven SCM plugin "diff" goal may have different interpretations in RTC depending on how | |
44 | // the user is using RTC. In one instance, the user may expect the diff to report back on the differences between | |
45 | // the local 'sandbox' and their connected repository workspace (ie. What files are 'unresolved'). | |
46 | // Other users may want the diff the report back the differences between their connected repository workspace | |
47 | // and the stream that it flows with (ie. What files are 'outgoing' / 'incoming'). | |
48 | // As a first step, we would have to figure out how to distinguish between these two use cases when using this goal. | |
49 | ||
50 | // Whilst, the above is true, based upon the SVN implementation, its diff does a difference | |
51 | // between the local working copy (sandbox) vs's repository (workspace repository). | |
52 | // | |
53 | // So this implementation will compare the sandbox with the workspace repository (even if there is | |
54 | // a valid flow target). As the "scm diff" command does not support this direct comparison (I have | |
55 | // had an Enhancement Work Item opened to do so), we will call the "scm status" command to get all | |
56 | // of the change files, and then iterate through all of them to get a diff of all of them. The combined | |
57 | // output of all of the various diffs will then be returned as a single output operation. | |
58 | // -Chris 24/02/12 | |
59 | ||
60 | // The following RTC commands may be useful however it retrieving the required information. | |
61 | // | |
62 | // 1. RTC "compare" command: Compare two workspaces/streams/baselines/snapshots, showing differing baselines and change sets. | |
63 | // See the following links for additional information on the RTC "compare" command: | |
64 | // RTC 2.0.0.2: | |
65 | // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_compare.html | |
66 | // RTC 3.0: | |
67 | // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_compare.html | |
68 | // RTC 3.0.1: | |
69 | // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_compare.html | |
70 | // | |
71 | // 2. RTC "diff" command: Compare two states of a file. | |
72 | // See the following links for additional information on the RTC "diff" command: | |
73 | // RTC 2.0.0.2: | |
74 | // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_diff.html | |
75 | // RTC 3.0: | |
76 | // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_diff.html | |
77 | // RTC 3.0.1: | |
78 | // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_diff.html | |
79 | // | |
80 | // 3. RTC "status" command: Show modification status of items in a workspace. | |
81 | // See the following links for additional information on the RTC "status" command: | |
82 | // RTC 2.0.0.2: | |
83 | // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_status.html | |
84 | // RTC 3.0: | |
85 | // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_status.html | |
86 | // RTC 3.0.1: | |
87 | // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_status.html | |
88 | // | |
89 | ||
90 | /** | |
91 | * @author <a href="mailto:ChrisGWarp@gmail.com">Chris Graham</a> | |
92 | */ | |
93 | 1 | public class JazzDiffCommand |
94 | extends AbstractDiffCommand | |
95 | { | |
96 | /** | |
97 | * {@inheritDoc} | |
98 | */ | |
99 | protected DiffScmResult executeDiffCommand( ScmProviderRepository repo, ScmFileSet fileSet, | |
100 | ScmVersion startRevision, ScmVersion endRevision ) | |
101 | throws ScmException | |
102 | { | |
103 | 0 | if ( getLogger().isDebugEnabled() ) |
104 | { | |
105 | 0 | getLogger().debug( "Executing diff command..." ); |
106 | } | |
107 | ||
108 | 0 | File baseDir = fileSet.getBasedir(); |
109 | 0 | File parentFolder = ( baseDir.getParentFile() != null ) ? baseDir.getParentFile() : baseDir; |
110 | ||
111 | // First execute the status command to get the list of changed files. | |
112 | 0 | JazzStatusCommand statusCmd = new JazzStatusCommand(); |
113 | 0 | statusCmd.setLogger( getLogger() ); |
114 | 0 | StatusScmResult statusCmdResult = statusCmd.executeStatusCommand( repo, fileSet ); |
115 | 0 | List<ScmFile> statusScmFiles = statusCmdResult.getChangedFiles(); |
116 | ||
117 | // In this case, we also use it across multiple calls to "scm diff" so that we | |
118 | // sum all output into on. | |
119 | 0 | JazzScmCommand diffCmd = null; |
120 | 0 | StringBuilder patch = new StringBuilder(); |
121 | 0 | Map<String, CharSequence> differences = new HashMap<String, CharSequence>(); |
122 | ||
123 | // Now lets iterate through them | |
124 | 0 | for ( Iterator<ScmFile> it = statusScmFiles.iterator(); it.hasNext(); ) |
125 | { | |
126 | 0 | ScmFile file = (ScmFile) it.next(); |
127 | 0 | if ( file.getStatus() == ScmFileStatus.MODIFIED ) |
128 | { | |
129 | // The "scm status" command returns files relative to the sandbox root. | |
130 | // Whereas the "scm diff" command needs them relative to the working directory. | |
131 | 0 | File fullPath = new File( parentFolder, file.getPath() ); |
132 | 0 | String relativePath = fullPath.toString().substring( baseDir.toString().length() ); |
133 | 0 | getLogger().debug( "Full Path : '" + fullPath + "'" ); |
134 | 0 | getLogger().debug( "Relative Path : '" + relativePath + "'" ); |
135 | ||
136 | // Now call "scm diff on it" | |
137 | // In this case, we use the DebugLoggerConsumer's ability to store captured output | |
138 | 0 | DebugLoggerConsumer diffConsumer = new DebugLoggerConsumer( getLogger() ); |
139 | 0 | ErrorConsumer errConsumer = new ErrorConsumer( getLogger() ); |
140 | 0 | diffCmd = createDiffCommand( repo, fileSet, relativePath ); |
141 | 0 | int status = diffCmd.execute( diffConsumer, errConsumer ); |
142 | 0 | if ( status != 0 || errConsumer.hasBeenFed() ) |
143 | { | |
144 | // Return a false result (not the usual SCMResult) | |
145 | 0 | return new DiffScmResult( diffCmd.toString(), "The scm diff command failed.", |
146 | errConsumer.getOutput(), false ); | |
147 | } | |
148 | // Append to patch (all combined) | |
149 | 0 | patch.append( diffConsumer.getOutput() ); |
150 | // Set the differences map <File, <CharSequence> | |
151 | 0 | differences.put( relativePath, diffConsumer.getOutput() ); |
152 | } | |
153 | 0 | } |
154 | ||
155 | 0 | return new DiffScmResult( diffCmd.toString(), statusCmdResult.getChangedFiles(), differences, |
156 | patch.toString() ); | |
157 | } | |
158 | ||
159 | public JazzScmCommand createDiffCommand( ScmProviderRepository repo, ScmFileSet fileSet, String relativePath ) | |
160 | { | |
161 | 1 | JazzScmCommand command = new JazzScmCommand( JazzConstants.CMD_DIFF, repo, fileSet, getLogger() ); |
162 | 1 | command.addArgument( JazzConstants.ARG_FILE ); |
163 | 1 | command.addArgument( relativePath ); |
164 | 1 | return command; |
165 | } | |
166 | } |