View Javadoc

1   /*
2   Karma core - Core of the Karma application
3   Copyright (C) 2004  Toolforge <www.toolforge.nl>
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19  package nl.toolforge.karma.core.cmd.impl;
20  
21  import nl.toolforge.karma.core.Patch;
22  import nl.toolforge.karma.core.Version;
23  import nl.toolforge.karma.core.cmd.CommandDescriptor;
24  import nl.toolforge.karma.core.cmd.CommandException;
25  import nl.toolforge.karma.core.cmd.CommandResponse;
26  import nl.toolforge.karma.core.cmd.DefaultCommand;
27  import nl.toolforge.karma.core.cmd.event.MessageEvent;
28  import nl.toolforge.karma.core.cmd.event.SimpleMessage;
29  import nl.toolforge.karma.core.manifest.Manifest;
30  import nl.toolforge.karma.core.manifest.ManifestException;
31  import nl.toolforge.karma.core.manifest.ReleaseManifest;
32  import nl.toolforge.karma.core.module.Module;
33  import nl.toolforge.karma.core.vc.AuthenticationException;
34  import nl.toolforge.karma.core.vc.RunnerFactory;
35  import nl.toolforge.karma.core.vc.VersionControlException;
36  import nl.toolforge.karma.core.vc.cvsimpl.CVSRunner;
37  import nl.toolforge.karma.core.vc.cvsimpl.Utils;
38  
39  import java.util.regex.PatternSyntaxException;
40  
41  /***
42   * <p>This command updates a module on a developers' local system. When the module has not been updated before, the
43   * module will be checked out (this is transparent for the user). The syntax for this command is:
44   * <p/>
45   * <pre>update-module -m, --module-name &lt;module-name&gt; [ -v &lt;version-number&gt; ]</pre
46   * <p/>
47   * <p>The <code>m</code> option specifies the module that should be updated. The <code>v</code> option specifies a
48   * specific version that should be fetched. The <code>v</code> option implies that the module is updated to
49   * <code>STATIC</code> state, regardless of the configuration for the module in the manifest. This state can be revoked
50   * by updating the module without specifying the <code>v</code> option. Karma will apply pattern rules to determine the
51   * actual symbolic name that is used in the version control system for the version.
52   *
53   * @author D.A. Smedes
54   * @version $Id: UpdateModuleCommand.java,v 1.56 2004/11/10 23:53:09 asmedes Exp $
55   */
56  public class UpdateModuleCommand extends DefaultCommand {
57  
58    protected CommandResponse response = new CommandResponse();
59  
60    /***
61     * Creates a <code>UpdateModuleCommand</code> for module <code>module</code> that should be updated. This module
62     * requires an <code>Option</code>
63     *
64     * @param descriptor The command descriptor for this command.
65     */
66    public UpdateModuleCommand(CommandDescriptor descriptor) {
67      super(descriptor);
68    }
69  
70    /***
71     * This command will update the module from the version control system. An update is done when
72     * the module is already present, otherwise a checkout will be performed. The checkout directory for the module
73     * is relative to the root directory of the <code>active</code> manifest.
74     */
75    public void execute() throws CommandException {
76  
77      String moduleName = "";
78      Module module = null;
79      Manifest manifest = null;
80  
81      // A manifest must be present for this command
82      //
83      if (!getContext().isManifestLoaded()) {
84        throw new CommandException(ManifestException.NO_ACTIVE_MANIFEST);
85      }
86  
87      moduleName = getCommandLine().getOptionValue("m");
88      try {
89        manifest = getContext().getCurrentManifest();
90        module = manifest.getModule(moduleName);
91      } catch (ManifestException e) {
92        throw new CommandException(e.getErrorCode(),e.getMessageArguments());
93      }
94  
95      // If the module is in working state, we don't need to determine a version.
96      //
97      Version version = null;
98  
99      if (!manifest.getState(module).equals(Module.WORKING)) { // Saves time ...
100 
101       if (getCommandLine().getOptionValue("v") != null) {
102         // The module should be updated to a specific version.
103         //
104         try {
105 
106           // Are we requesting a patch or a normal version ?
107           //
108           String manualVersion = getCommandLine().getOptionValue("v");
109           if (manualVersion.matches(Patch.VERSION_PATTERN_STRING)) {
110             version = new Patch(manualVersion);
111           } else {
112             version = new Version(manualVersion);
113           }
114         } catch (PatternSyntaxException pse) {
115           throw new CommandException(CommandException.INVALID_ARGUMENT,
116               new Object[]{getCommandLine().getOptionValue("v"),
117                            "Version has to be <number>-<number>[-<number>], e.g. '0-0'"});
118         }
119       } else if (manifest.getState(module).equals(Module.STATIC)) {
120         version = module.getVersion();
121       } else if (manifest.getState(module).equals(Module.DYNAMIC)) {
122         // todo CVSVersionExtractor should be retrieved through a Factory.
123         //
124         try {
125           version = Utils.getLastVersion(module);
126         } catch (VersionControlException e) {
127           throw new CommandException(e.getErrorCode(), e.getMessageArguments());
128         }
129       }
130     }
131 
132     try {
133       if (version != null && !manifest.getState(module).equals(Module.WORKING) && version.equals(Utils.getLocalVersion(module))) {
134         // todo message to be internationalized.
135         //
136 
137         // No need to update.
138         //
139         response.addEvent(
140             new MessageEvent(this, new SimpleMessage("Module `" + module.getName() + "` is already up-to-date with version `" + version.toString() + "`.")));
141 
142       } else {
143 
144         CVSRunner runner = (CVSRunner) RunnerFactory.getRunner(module.getLocation());
145         runner.setCommandResponse(response);
146 
147         if (!Utils.existsInRepository(module)) {
148           throw new CommandException(VersionControlException.MODULE_NOT_IN_REPOSITORY, new Object[]{module.getName(), module.getLocation().getId()});
149         }
150 
151         //todo check whether the requested version does exist for the module.
152 
153         if (manifest.getState(module).equals(Module.WORKING) && manifest instanceof ReleaseManifest) {
154           runner.checkout(module, module.getPatchLine(), null);
155         } else {
156           runner.checkout(module, version);
157         }
158 
159         SimpleMessage message = null;
160         // todo message to be internationalized.
161         if (version == null) {
162           // No state change.
163           //
164           message = new SimpleMessage("Module `" + module.getName() + "` updated.");
165         } else {
166           if (manifest instanceof ReleaseManifest) {
167             manifest.setState(module, Module.STATIC);
168             message = new SimpleMessage("Module `" + module.getName() + "` updated with version `" + version.toString() + "`; state set to STATIC.");
169           } else {
170             if (manifest.getState(module).equals(Module.STATIC)) {
171               // The module was static.
172               //
173               message = new SimpleMessage("Module `" + module.getName() + "` updated.");
174             } else {
175               manifest.setState(module, Module.DYNAMIC);
176               message = new SimpleMessage("Module `" + module.getName() + "` updated with version `" + version.toString() + "`; state set to DYNAMIC.");
177             }
178           }
179         }
180         response.addEvent(new MessageEvent(this, message));
181       }
182     } catch (VersionControlException e) {
183       throw new CommandException(e.getErrorCode(), e.getMessageArguments());
184     } catch (AuthenticationException e) {
185       throw new CommandException(e.getErrorCode(), e.getMessageArguments());
186     }
187   }
188 
189   public CommandResponse getCommandResponse() {
190     return response;
191   }
192 }