KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > cvsclient > command > checkout > CheckoutCommand


1 /*****************************************************************************
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is the CVS Client Library.
16  * The Initial Developer of the Original Software is Robert Greig.
17  * Portions created by Robert Greig are Copyright (C) 2000.
18  * All Rights Reserved.
19  *
20  * Contributor(s): Robert Greig.
21  *****************************************************************************/

22 package org.netbeans.lib.cvsclient.command.checkout;
23
24 import java.io.*;
25 import java.util.*;
26
27 import org.netbeans.lib.cvsclient.*;
28 import org.netbeans.lib.cvsclient.command.*;
29 import org.netbeans.lib.cvsclient.command.update.*;
30 import org.netbeans.lib.cvsclient.connection.*;
31 import org.netbeans.lib.cvsclient.event.*;
32 import org.netbeans.lib.cvsclient.request.*;
33
34 /**
35  * The checkout command.
36  * This handles the sending of the requests and the processing of the responses
37  * from the server.
38  *
39  * @author Robert Greig
40  */

41 public class CheckoutCommand extends BasicCommand
42         implements TemporaryFileCreator {
43             
44     private static final String JavaDoc UPDATING = ": Updating "; // NOI18N
45
/**
46      * A store of potentially empty directories. When a directory has a file
47      * in it, it is removed from this set. This set allows the prune option
48      * to be implemented.
49      */

50     private final Set emptyDirectories = new HashSet();
51
52     /**
53      * The modules to checkout. These names are unexpanded and will be passed
54      * to a module-expansion request.
55      */

56     private final List modules = new LinkedList();
57
58     /**
59      * The expanded modules.
60      */

61     private final List expandedModules = new LinkedList();
62
63     /**
64      * Will force the checkout command to display only a list of modules.
65      */

66     private boolean showModules;
67
68     /**
69      * if set, will display just a list of modules with statuses.
70      */

71     private boolean showModulesWithStatus;
72
73     /**
74      * if set, will redirect the output of the command to standard output.
75      */

76     private boolean pipeToOutput;
77
78     /**
79      * Whether to prune directories, i.e. remove any directories that do not
80      * contain any files. This is the -P option in command-line CVS.
81      */

82     private boolean pruneDirectories;
83
84     /**
85      * Resets any sticky tags/dates/options imposed on the updated file(s).
86      */

87     private boolean resetStickyOnes;
88
89     /**
90      * Use head revision if a revision meeting criteria set by switches -r/-D
91      * (tag/date) is not found.
92      */

93     private boolean useHeadIfNotFound;
94     
95     /**
96      * Don't shorten module paths if -d specified.
97      */

98     private boolean notShortenPaths;
99     
100     /**
101      * Whether <code>notShortenPaths</code> was explicitly set.
102      */

103     private boolean isNotShortenSet;
104
105     /**
106      * Forces a checkout of a revision that was current at specified date.
107      */

108     private String JavaDoc checkoutByDate;
109
110     /**
111      * Forces a checkout of specified revision. Can be a number/tag/branch
112      */

113     private String JavaDoc checkoutByRevision;
114
115     /**
116      * performs checkout to specified directory other then the module.
117      */

118     private String JavaDoc checkoutDirectory;
119
120     /**
121      * Use this keyword substitution for the command.
122      * does not include the -k switch part.
123      */

124     private KeywordSubstitutionOptions keywordSubst;
125     
126     /**
127      * Do not run module program (if any).
128      */

129     private boolean notRunModuleProgram;
130
131     /** Active during execute. */
132     private ClientServices client;
133
134     /**
135      * Construct a new checkout command.
136      * @param recursive whether to do a recursive checkout
137      * @param modules an array of modules names to checkout
138      */

139     public CheckoutCommand(boolean recursive, String JavaDoc[] modules) {
140         resetCVSCommand();
141         setRecursive(recursive);
142         setModules(modules);
143     }
144
145     /**
146      * Construct a new checkout command.
147      * @param recursive whether to do a recursive checkout
148      * @param module the module to checkout
149      */

150     public CheckoutCommand(boolean recursive, String JavaDoc module) {
151         resetCVSCommand();
152         setRecursive(recursive);
153         setModule(module);
154     }
155
156     /**
157      * Construct a checkout command, with default values for options.
158      */

159     public CheckoutCommand() {
160         resetCVSCommand();
161         setRecursive(true);
162     }
163
164     /**
165      * Set the modules to checkout.
166      * @param theModules the names (it's like relative path) of the modules to checkout
167      */

168     public void setModule(String JavaDoc module) {
169         modules.add(module);
170     }
171
172     /**
173      * clears the list of modules for checkout.
174      */

175
176     public void clearModules() {
177         this.modules.clear();
178     }
179
180     /**
181      * Set the modules to checkout.
182      * @param theModules the names of the modules to checkout
183      */

184     public void setModules(String JavaDoc[] modules) {
185         clearModules();
186         for (int i = 0; i < modules.length; i++) {
187             String JavaDoc module = modules[i];
188             this.modules.add(module);
189         }
190     }
191
192     public String JavaDoc[] getModules() {
193         String JavaDoc[] mods = new String JavaDoc[modules.size()];
194         mods = (String JavaDoc[])modules.toArray(mods);
195         return mods;
196     }
197
198     /**
199      * Handle modules that are already checked out. We check whether a
200      * module has been checked out and if so we add it to the list of
201      * directories that the superclass must send Modified requests for etc.
202      */

203     private void processExistingModules(String JavaDoc localPath) {
204         if (expandedModules.size() == 0) {
205             return;
206         }
207
208         List list = new ArrayList(expandedModules.size());
209         for (Iterator it = expandedModules.iterator(); it.hasNext();) {
210             String JavaDoc moduleName = (String JavaDoc)it.next();
211             if (moduleName.equals(".")) { //NOI18N
212
list.add(new File(localPath));
213                 break;
214             }
215             File moduleDir = null;
216             final File moduleFile = new File(localPath, moduleName);
217             if (moduleFile.isFile()) {
218                 moduleDir = moduleFile.getParentFile();
219             }
220             else {
221                 moduleDir = moduleFile;
222             }
223             final File moduleCVSDir = new File(moduleDir, "CVS/Repository"); //NOI18N
224
if (moduleCVSDir.exists()) {
225                 list.add(moduleFile);
226             }
227         }
228         File[] directories = new File[list.size()];
229         directories = (File[])list.toArray(directories);
230         setFiles(directories);
231     }
232
233     /**
234      * Execute this command.
235      * @param client the client services object that provides any necessary
236      * services to this command, including the ability to actually process
237      * all the requests
238      */

239     public void execute(ClientServices client, EventManager em)
240             throws CommandException, AuthenticationException {
241
242         client.ensureConnection();
243         this.client = client;
244
245         try {
246             requests = new LinkedList();
247             if (client.isFirstCommand()) {
248                 requests.add(new RootRequest(client.getRepository()));
249             }
250
251             if (showModules || showModulesWithStatus) {
252                 // we need to initialize the builder first (is done in BuildableCommand.execute()
253
// but we can't run it because of teh BasicCommand's execute and
254
// it's feature that adds the files request to the request list.
255
if (builder == null && !isBuilderSet()) {
256                     builder = createBuilder(em);
257                 }
258
259                 // special handling for -c -s switches.
260
if (showModules) {
261                     requests.add(new ArgumentRequest("-c")); //NOI18N
262
}
263                 if (showModulesWithStatus) {
264                     requests.add(new ArgumentRequest("-s")); //NOI18N
265
}
266                 requests.add(CommandRequest.CHECKOUT);
267                 try {
268                     client.processRequests(requests);
269                     requests.clear();
270                 }
271                 catch (CommandException ex) {
272                     throw ex;
273                 }
274                 catch (EOFException ex) {
275                     throw new CommandException(ex, CommandException.getLocalMessage("CommandException.EndOfFile", null)); //NOI18N
276
}
277                 catch (Exception JavaDoc ex) {
278                     throw new CommandException(ex, ex.getLocalizedMessage());
279                 }
280                 return;
281             }
282
283             for (Iterator it = modules.iterator(); it.hasNext();) {
284                 String JavaDoc module = (String JavaDoc)it.next();
285                 requests.add(new ArgumentRequest(module));
286             }
287
288             expandedModules.clear();
289             requests.add(new DirectoryRequest(".", client.getRepository())); //NOI18N
290
requests.add(new RootRequest(client.getRepository()));
291             requests.add(new ExpandModulesRequest());
292             try {
293                 client.processRequests(requests);
294             }
295             catch (CommandException ex) {
296                 throw ex;
297             }
298             catch (Exception JavaDoc ex) {
299                 throw new CommandException(ex, ex.getLocalizedMessage());
300             }
301             requests.clear();
302             postExpansionExecute(client, em);
303         } finally {
304             this.client = null;
305         }
306     }
307
308     /**
309      * The result from this command is used only when the getFiles() returns null or empty array.
310      * in such a case and when this method returns true, it is assumed the localpath should be taken
311      * as the 'default' file for the building of requests.
312      * in checkout we operate with modules rather then files. This produces problems in the following situation.
313      * If you have something already checked out and want to checkout another module that is not checked out yet,
314      * then there's nothing to be translated from modules to files. and in such a case the localpathis assumed,
315      * which includes non-relevant already checked out directories..
316      */

317     protected boolean assumeLocalPathWhenUnspecified() {
318         return false;
319     }
320
321     /**
322      * This is called when the server has responded to an expand-modules
323      * request.
324      */

325     public void moduleExpanded(ModuleExpansionEvent e) {
326         expandedModules.add(e.getModule());
327     }
328
329     /**
330      * Execute this command
331      * @param client the client services object that provides any necessary
332      * services to this command, including the ability to actually process
333      * all the requests
334      */

335     private void postExpansionExecute(ClientServices client, EventManager em)
336             throws CommandException, AuthenticationException {
337         // we first test whether the modules specified actually exist
338
// checked out already. If so, we must work something like an update
339
// command and send modified files to the server.
340
processExistingModules(client.getLocalPath());
341         // the sending of the Modified requests and so on is handled in the
342
// superclass.
343
super.execute(client, em);
344
345         //
346
// moved modules code to the end of the other arguments --GAR
347
//
348
int index = requests.size();
349         final int FIRST_INDEX = 0;
350         final int SECOND_INDEX = 1;
351         if (!isRecursive()) {
352             requests.add(FIRST_INDEX, new ArgumentRequest("-l")); //NOI18N
353
}
354         if (pipeToOutput) {
355             requests.add(FIRST_INDEX, new ArgumentRequest("-p")); //NOI18N
356
}
357         if (resetStickyOnes) {
358             requests.add(FIRST_INDEX, new ArgumentRequest("-A")); //NOI18N
359
}
360         if (useHeadIfNotFound) {
361             requests.add(FIRST_INDEX, new ArgumentRequest("-f")); //NOI18N
362
}
363         if (isNotShortenPaths()) {
364             requests.add(FIRST_INDEX, new ArgumentRequest("-N")); //NOI18N
365
}
366         if (notRunModuleProgram) {
367             requests.add(FIRST_INDEX, new ArgumentRequest("-n")); //NOI18N
368
}
369         if (checkoutByDate != null && checkoutByDate.length() > 0) {
370             requests.add(FIRST_INDEX, new ArgumentRequest("-D")); //NOI18N
371
requests.add(SECOND_INDEX, new ArgumentRequest(getCheckoutByDate()));
372         }
373         if (checkoutByRevision != null && checkoutByRevision.length() > 0) {
374             requests.add(FIRST_INDEX, new ArgumentRequest("-r")); //NOI18N
375
requests.add(SECOND_INDEX, new ArgumentRequest(getCheckoutByRevision()));
376         }
377         if (checkoutDirectory != null && (!checkoutDirectory.equals(""))) {
378             requests.add(FIRST_INDEX, new ArgumentRequest("-d")); //NOI18N
379
requests.add(SECOND_INDEX, new ArgumentRequest(getCheckoutDirectory()));
380         }
381         if (getKeywordSubst() != null) {
382             requests.add(FIRST_INDEX, new ArgumentRequest("-k" + getKeywordSubst())); //NOI18N
383
}
384         
385         index = requests.size() - index; // The end of our arguments
386
// Add a -- before the first file name just in case it looks like an option.
387
requests.add(index++, new ArgumentRequest("--")); // NOI18N
388

389         // Note that modules might be null and still be valid because
390
// for -c, -s switches no module has to be selected
391
// You might also think that we should pass in expandedModules here
392
// but according to the spec that would be wrong because of the -d
393
// flag.
394
for (Iterator it = modules.iterator(); it.hasNext();) {
395             String JavaDoc module = (String JavaDoc)it.next();
396             requests.add(index++, new ArgumentRequest(module));
397         }
398
399         requests.add(new DirectoryRequest(".", client.getRepository())); //NOI18N
400
requests.add(CommandRequest.CHECKOUT);
401         try {
402             client.processRequests(requests);
403             if (pruneDirectories) {
404                 pruneEmptyDirectories();
405             }
406             requests.clear();
407
408         }
409         catch (CommandException ex) {
410             throw ex;
411         }
412         catch (Exception JavaDoc ex) {
413             throw new CommandException(ex, ex.getLocalizedMessage());
414         }
415     }
416
417     /**
418      * Getter for property showModules.
419      * @return Value of property showModules.
420      */

421     public boolean isShowModules() {
422         return showModules;
423     }
424
425     /**
426      * Setter for property showModules.
427      * @param showModules New value of property showModules.
428      */

429     public void setShowModules(boolean showModules) {
430         this.showModules = showModules;
431     }
432
433     /**
434      * Getter for property showModulesWithStatus.
435      * @return Value of property showModulesWithStatus.
436      */

437     public boolean isShowModulesWithStatus() {
438         return showModulesWithStatus;
439     }
440
441     /**
442      * Setter for property showModulesWithStatus.
443      * @param showModulesWithStatus New value of property showModulesWithStatus.
444      */

445     public void setShowModulesWithStatus(boolean showModulesWithStatus) {
446         this.showModulesWithStatus = showModulesWithStatus;
447     }
448
449     /**
450      * Set whether to prune directories.
451      * This is the -P option in the command-line CVS.
452      */

453     public void setPruneDirectories(boolean pruneDirectories) {
454         this.pruneDirectories = pruneDirectories;
455     }
456
457     /**
458      * Get whether to prune directories.
459      * @return true if directories should be removed if they contain no files,
460      * false otherwise.
461      */

462     public boolean getPruneDirectories() {
463         return pruneDirectories;
464     }
465
466     /**
467      * Getter for property pipeToOutput.
468      * @return Value of property pipeToOutput.
469      */

470     public boolean isPipeToOutput() {
471         return pipeToOutput;
472     }
473
474     /**
475      * Setter for property pipeToOutput.
476      * @param pipeToOutput New value of property pipeToOutput.
477      */

478     public void setPipeToOutput(boolean pipeToOutput) {
479         this.pipeToOutput = pipeToOutput;
480     }
481
482     /**
483      * Getter for property resetStickyOnes.
484      * @return Value of property resetStickyOnes.
485      */

486     public boolean isResetStickyOnes() {
487         return resetStickyOnes;
488     }
489
490     /**
491      * Setter for property resetStickyOnes.
492      * @param resetStickyOnes New value of property resetStickyOnes.
493      */

494     public void setResetStickyOnes(boolean resetStickyOnes) {
495         this.resetStickyOnes = resetStickyOnes;
496     }
497
498     /**
499      * Getter for property useHeadIfNotFound.
500      * @return Value of property useHeadIfNotFound.
501      */

502     public boolean isUseHeadIfNotFound() {
503         return useHeadIfNotFound;
504     }
505
506     /**
507      * Setter for property useHeadIfNotFound.
508      * @param useHeadIfNotFound New value of property useHeadIfNotFound.
509      */

510     public void setUseHeadIfNotFound(boolean useHeadIfNotFound) {
511         this.useHeadIfNotFound = useHeadIfNotFound;
512     }
513     
514     /**
515      * Getter for property notShortenPaths.
516      * @return Value of property notShortenPaths.
517      */

518     public boolean isNotShortenPaths() {
519         // Use the same logic as cvs from cvshome.org.
520
return notShortenPaths || (!isNotShortenSet && checkoutDirectory == null);
521     }
522     
523     /**
524      * Setter for property notShortenPaths.
525      * @param notShortenPaths New value of property notShortenPaths.
526      */

527     public void setNotShortenPaths(boolean notShortenPaths) {
528         this.notShortenPaths = notShortenPaths;
529         isNotShortenSet = true;
530     }
531     
532     /**
533      * Getter for property notRunModuleProgram.
534      * @return Value of property notRunModuleProgram.
535      */

536     public boolean isNotRunModuleProgram() {
537         return notRunModuleProgram;
538     }
539     
540     /**
541      * Setter for property notRunModuleProgram.
542      * @param notRunModuleProgram New value of property notRunModuleProgram.
543      */

544     public void setNotRunModuleProgram(boolean notRunModuleProgram) {
545         this.notRunModuleProgram = notRunModuleProgram;
546     }
547     
548     /**
549      * Getter for property checkoutByDate.
550      * @return Value of property checkoutByDate.
551      */

552     public String JavaDoc getCheckoutByDate() {
553         return checkoutByDate;
554     }
555
556     /**
557      * Setter for property checkoutByDate.
558      * @param checkoutByDate New value of property checkoutByDate.
559      */

560     public void setCheckoutByDate(String JavaDoc checkoutByDate) {
561         this.checkoutByDate = checkoutByDate;
562     }
563
564     /**
565      * Getter for property checkoutByRevision.
566      * @return Value of property checkoutByRevision.
567      */

568     public String JavaDoc getCheckoutByRevision() {
569         return checkoutByRevision;
570     }
571
572     /**
573      * Setter for property checkoutByRevision.
574      * @param checkoutByRevision New value of property checkoutByRevision.
575      */

576     public void setCheckoutByRevision(String JavaDoc checkoutByRevision) {
577         this.checkoutByRevision = checkoutByRevision;
578     }
579
580     /** Getter for property checkoutDirectory.
581      * @return Value of property checkoutDirectory.
582      */

583     public String JavaDoc getCheckoutDirectory() {
584         return this.checkoutDirectory;
585     }
586
587     /** Setter for property checkoutDirectory.
588      * @param checkoutDirectory New value of property checkoutDirectory.
589      */

590     public void setCheckoutDirectory(String JavaDoc checkoutDirectory) {
591         this.checkoutDirectory = checkoutDirectory;
592     }
593
594     /**
595      * Getter for property keywordSubst.
596      * @return Value of property keywordSubst.
597      */

598     public KeywordSubstitutionOptions getKeywordSubst() {
599         return keywordSubst;
600     }
601
602     /**
603      * Setter for property keywordSubst.
604      * @param keywordSubst New value of property keywordSubst.
605      */

606     public void setKeywordSubst(KeywordSubstitutionOptions keywordSubst) {
607         this.keywordSubst = keywordSubst;
608     }
609
610     public Builder createBuilder(EventManager eventMan) {
611         if (isShowModules() || isShowModulesWithStatus()) {
612             return new ModuleListBuilder(eventMan, this);
613         }
614         if (isPipeToOutput()) {
615             return new PipedFilesBuilder(eventMan, this, this);
616         }
617         return new UpdateBuilder(eventMan, getLocalDirectory());
618     }
619
620     public File createTempFile(String JavaDoc filename) throws IOException {
621         File temp = File.createTempFile("cvs", ".dff", getGlobalOptions().getTempDir()); //NOI18N
622
return temp;
623     }
624
625     /**
626      * This method returns how the command would looklike when typed on the command line.
627      * Each command is responsible for constructing this information.
628      * @returns <command's name> [<parameters>] files/dirs. Example: checkout -p CvsCommand.java
629      */

630     public String JavaDoc getCVSCommand() {
631         StringBuffer JavaDoc toReturn = new StringBuffer JavaDoc("checkout "); //NOI18N
632
toReturn.append(getCVSArguments());
633         if (!isShowModules() && !isShowModulesWithStatus()) {
634             for (Iterator it = modules.iterator(); it.hasNext();) {
635                 String JavaDoc module = (String JavaDoc)it.next();
636                 toReturn.append(module);
637                 toReturn.append(' ');
638             }
639         }
640         return toReturn.toString();
641     }
642
643     /**
644      * Takes the arguments and sets the command.
645      * To be mainly used for automatic settings (like parsing the .cvsrc file).
646      * @return true if the option (switch) was recognized and set
647      */

648     public boolean setCVSCommand(char opt, String JavaDoc optArg) {
649         if (opt == 'c') {
650             setShowModules(true);
651         }
652         else if (opt == 's') {
653             setShowModulesWithStatus(true);
654         }
655         else if (opt == 'p') {
656             setPipeToOutput(true);
657         }
658         else if (opt == 'R') {
659             setRecursive(true);
660         }
661         else if (opt == 'l') {
662             setRecursive(false);
663         }
664         else if (opt == 'A') {
665             setResetStickyOnes(true);
666         }
667         else if (opt == 'f') {
668             setUseHeadIfNotFound(true);
669         }
670         else if (opt == 'P') {
671             setPruneDirectories(true);
672         }
673         else if (opt == 'D') {
674             setCheckoutByDate(optArg.trim());
675         }
676         else if (opt == 'r') {
677             setCheckoutByRevision(optArg.trim());
678         }
679         else if (opt == 'd') {
680             setCheckoutDirectory(optArg);
681         }
682         else if (opt == 'N') {
683             setNotShortenPaths(true);
684         }
685         else if (opt == 'n') {
686             setNotRunModuleProgram(true);
687         }
688         else if (opt == 'k') {
689             KeywordSubstitutionOptions keywordSubst =
690                     KeywordSubstitutionOptions.findKeywordSubstOption(optArg);
691             setKeywordSubst(keywordSubst);
692         }
693         else {
694             return false;
695         }
696         return true;
697     }
698
699     /**
700      * String returned by this method defines which options are available for this particular command
701      */

702     public String JavaDoc getOptString() {
703         return "cnpslNPRAD:r:fk:d:"; //NOI18N
704
}
705
706     /**
707      * Resets all switches in the command.
708      * After calling this method, the command should have no switches defined
709      * and should behave defaultly.
710      */

711     public void resetCVSCommand() {
712         setShowModules(false);
713         setShowModulesWithStatus(false);
714         setPipeToOutput(false);
715         setRecursive(true);
716         setResetStickyOnes(false);
717         setUseHeadIfNotFound(false);
718         setCheckoutByDate(null);
719         setCheckoutByRevision(null);
720         setKeywordSubst(null);
721         setPruneDirectories(false);
722         setNotShortenPaths(false);
723         isNotShortenSet = false;
724         setNotRunModuleProgram(false);
725         setCheckoutDirectory(null);
726     }
727
728     /**
729      * Returns the arguments of the command in the command-line style.
730      * Similar to getCVSCommand() however without the files and command's name
731      */

732     public String JavaDoc getCVSArguments() {
733         StringBuffer JavaDoc toReturn = new StringBuffer JavaDoc(""); //NOI18N
734
if (isShowModules()) {
735             toReturn.append("-c "); //NOI18N
736
}
737         if (isShowModulesWithStatus()) {
738             toReturn.append("-s "); //NOI18N
739
}
740         if (isPipeToOutput()) {
741             toReturn.append("-p "); //NOI18N
742
}
743         if (!isRecursive()) {
744             toReturn.append("-l "); //NOI18N
745
}
746         if (isResetStickyOnes()) {
747             toReturn.append("-A "); //NOI18N
748
}
749         if (isUseHeadIfNotFound()) {
750             toReturn.append("-f "); //NOI18N
751
}
752         if (getPruneDirectories()) {
753             toReturn.append("-P "); //NOI18N
754
}
755         if (isNotShortenPaths()) {
756             toReturn.append("-N "); // NOI18N
757
}
758         if (isNotRunModuleProgram()) {
759             toReturn.append("-n "); // NOI18N
760
}
761         if (getKeywordSubst() != null) {
762             toReturn.append("-k"); //NOI18N
763
toReturn.append(getKeywordSubst());
764             toReturn.append(' ');
765         }
766         if (getCheckoutByRevision() != null && getCheckoutByRevision().length() > 0) {
767             toReturn.append("-r "); //NOI18N
768
toReturn.append(getCheckoutByRevision());
769             toReturn.append(' ');
770         }
771         if (getCheckoutByDate() != null && getCheckoutByDate().length() > 0) {
772             toReturn.append("-D "); //NOI18N
773
toReturn.append(getCheckoutByDate());
774             toReturn.append(' ');
775         }
776         if (getCheckoutDirectory() != null) {
777             toReturn.append("-d "); //NOI18N
778
toReturn.append(getCheckoutDirectory());
779             toReturn.append(" "); //NOI18N
780
}
781          return toReturn.toString();
782     }
783
784     /**
785      * Called when the server wants to send a message to be displayed to
786      * the user. The message is only for information purposes and clients
787      * can choose to ignore these messages if they wish.
788      * @param e the event
789      */

790     public void messageSent(MessageEvent e) {
791         super.messageSent(e);
792         // we use this event to determine which directories need to be checked
793
// for updating
794
if (pruneDirectories &&
795                 e.getMessage().indexOf(UPDATING) > 0) {
796             File file = new File(getLocalDirectory(), e.getMessage().substring(e.getMessage().indexOf(UPDATING) + UPDATING.length()));
797             emptyDirectories.add(file);
798         }
799     }
800
801     /**
802      * Prunes a directory, recursively pruning its subdirectories
803      * @param directory the directory to prune
804      */

805     private boolean pruneEmptyDirectory(File directory) throws IOException {
806         boolean empty = true;
807
808         final File[] contents = directory.listFiles();
809
810         // should never be null, but just in case...
811
if (contents != null) {
812             for (int i = 0; i < contents.length; i++) {
813                 if (contents[i].isFile()) {
814                     empty = false;
815                 }
816                 else {
817                     if (!contents[i].getName().equals("CVS")) { //NOI18N
818
empty = pruneEmptyDirectory(contents[i]);
819                     }
820                 }
821
822                 if (!empty) {
823                     break;
824                 }
825             }
826
827             if (empty) {
828                 // check this is a CVS directory and not some directory the user
829
// has stupidly called CVS...
830
final File entriesFile = new File(directory, "CVS/Entries"); //NOI18N
831
if (entriesFile.exists()) {
832                     final File adminDir = new File(directory, "CVS"); //NOI18N
833
final File[] adminFiles = adminDir.listFiles();
834                     for (int i = 0; i < adminFiles.length; i++) {
835                         adminFiles[i].delete();
836                     }
837                     adminDir.delete();
838                     directory.delete();
839                     client.removeEntry(directory);
840                 }
841             }
842         }
843
844         return empty;
845     }
846
847     /**
848      * Remove any directories that don't contain any files
849      */

850     private void pruneEmptyDirectories() throws IOException {
851         final Iterator it = emptyDirectories.iterator();
852         while (it.hasNext()) {
853             final File dir = (File)it.next();
854             // we might have deleted it already (due to recursive delete)
855
// so we need to check existence
856
if (dir.exists()) {
857                 pruneEmptyDirectory(dir);
858             }
859         }
860         emptyDirectories.clear();
861     }
862     
863 }
864
Popular Tags