SvnRepository.java
001 /*
002  *  SvnRepository.java
003  *  Copyright (c) 1998-2008, The University of Sheffield.
004  *
005  *  This code is from the GATE project (http://gate.ac.uk/) and is free
006  *  software licenced under the GNU General Public License version 3. It is
007  *  distributed without any warranty. For more details see COPYING.txt in the
008  *  top level directory (or at http://gatewiki.sf.net/COPYING.txt).
009  *  
010  *  Hamish Cunningham 27/Aug/2005
011  */
012 
013 package gate.versioning.cmdline;
014 import java.io.*;
015 import java.util.*;
016 import gate.util.*;
017 
018 /**
019  * SVN repository implementation.
020  * The public API of this class is documented on the
021  {@link Repository} interface.
022  @see gate.versioning.cmdline.Repository
023  */
024 public class SvnRepository extends AbstractRepository {
025 
026   /** Debug flag. */
027   private boolean DEBUG = false;
028 
029   /** Returns "svn". */
030   public String getCommandName() { return "svn"}
031 
032   /** Get the pre-subcommand elements of the command (e.g. -d root). */
033   protected List getPreCommand() {
034     List preCommand = new ArrayList();
035     return preCommand;
036   // getPreCommand()
037 
038   /** Get the post-subcommand elements of the command (e.g. root). */
039   protected List getPostCommand(String fileName, boolean noRoot) {
040     List postCommand = new ArrayList();
041     if(noRoot) {
042       if(fileName != null)
043         postCommand.add(fileName);
044     else {
045       if(fileName != null)
046         postCommand.add(root + "/" + fileName);
047       else
048         postCommand.add(root);
049     }
050 
051     return postCommand;
052   // getPostCommand()
053 
054   /**
055    * The root / URL of the repository. SVN doesn't like backslash here
056    * (at least on version 1.2.3 Windoze build run from cygwin or via
057    * Runtime.exec), so substitute them all for slash.
058    */
059   public void setRoot(String root) {
060     this.root = root.replaceAll("\\\\""/");
061   // setRoot()
062 
063   /**
064    * Commit changes.
065    @param fileName the file or directory to work on (should be relative
066    * to the repository's working directory, and use "/" as a path separator).
067    @param message a commit message.
068    @return boolean representing success or failure.
069    */
070   public boolean checkin(String fileName, String message) {
071     String[] com = buildCommandArray(fileName, "ci""-m" + message, true);
072     return runCommand(com);
073   // checkin()
074 
075   /**
076    * Update.
077    @param fileName the file or directory to work on (should be relative
078    * to the repository's working directory, and use "/" as a path separator).
079    @return boolean representing success or failure.
080    */
081   public boolean update(String fileName) {
082     String[] com = buildCommandArray(fileName, "update", null, true);
083     return runCommand(com);
084   // update()
085 
086   /**
087    * Status.
088    @param fileName the file or directory to work on (should be relative
089    * to the repository's working directory, and use "/" as a path separator).
090    @return String giving status ouput.
091    */
092   public String status(String fileName) {
093     String[] com = buildCommandArray(
094       fileName, "status""--show-updates"true
095     );
096     if(! runCommand(com))
097       return null;
098     else
099       return getCommandStdout();
100   // status()
101 
102   /**
103    * Delete from the repository.
104    @param fileName the file or directory to work on (should be relative
105    * to the repository's working directory, and use "/" as a path separator).
106    @return boolean representing success or failure.
107    */
108   public boolean delete(String fileName) {
109     String[] com = buildCommandArray(fileName, "delete", null, true);
110     return runCommand(com);
111   // delete()
112 
113   /**
114    * Add to the repository.
115    @param fileName the file or directory to work on (should be relative
116    * to the repository's working directory, and use "/" as a path separator).
117    @return boolean representing success or failure.
118    */
119   public boolean add(String fileName) {
120     String[] com = buildCommandArray(fileName, "add", null, true);
121     return runCommand(com);
122   // add()
123 
124   /**
125    * Get the difference with the repository version.
126    @param fileName the file or directory to work on (should be relative
127    * to the repository's working directory, and use "/" as a path separator).
128    @return a string containing the difference, or "" for no difference, or
129    * null for error.
130    */
131   public String diff(String fileName) {
132     String[] com = buildCommandArray(fileName, "diff", null, true);
133     if(! runCommand(com, true))
134       return null;
135     return getCommandStdout();
136   // diff()
137 
138   /** 
139    * Create a new repository filetree (i.e. not a new object but a new
140    * database/filesystem on disk).
141    * This method can be called before {@link #init} (so that we
142    * can create repositories without having an existing one).
143    @param dirName the directory to work on, which will be created
144    * (should be an absolute path).
145    @return boolean representing success or failure.
146    */
147   public boolean create(String dirName) {
148     String[] command = new String[5];
149     command[0"svnadmin";
150     command[1"create";
151     command[2"--fs-type";
152     command[3"fsfs";
153     command[4= dirName;
154 
155     boolean result = runCommand(command);
156     return result;
157   // create()
158 
159   /** 
160    * Import a directory.
161    @param dirName the directory to import (this must exist).
162    @return boolean representing success or failure.
163    @throws GateException when the directory doesn't exist.
164    */
165   public boolean importDir(String dirNamethrows GateException {
166     File dir = new File(dirName);
167     if(! dir.exists() || ! dir.isDirectory())
168       throw new GateException(dirName + " is not an existing directory");
169 
170     List com = new ArrayList();
171     com.add(getCommandName());
172     com.add("import");
173     com.add("-m");
174     com.add("imported");
175     com.add(dir.getName());
176     com.add(getRoot() "/" + dir.getName());
177     String[] comArray = (String[]) com.toArray(new String[com.size()]);
178     
179     // adjust working directory for duration of command
180     File oldWorkingDir = workingDir;
181     workingDir = dir.getParentFile();
182     boolean result = runCommand(comArray);
183     workingDir = oldWorkingDir;    
184     
185     return result;
186   // importDir()
187 
188   /**
189    * Use the repository's status command to figure out if the file has been
190    * locally modified.
191    @param fileName the file or directory to work on (should be relative
192    * to the repository's working directory, and use "/" as a path separator).
193    @return boolean giving status indication.
194    */
195   public boolean isModified(String fileName) {
196     String statusString = status(fileName);
197     if(DEBUGOut.prln(">>" + statusString + "<<");
198     if(statusString != null && statusString.startsWith("M"))
199       return true;
200     else
201       return false;
202   // isModified()
203 
204   /**
205    * Use the repository's status command to figure out if the file is
206    * out-of-date.
207    @param fileName the file or directory to work on (should be relative
208    * to the repository's working directory, and use "/" as a path separator).
209    @return boolean giving status indication.
210    */
211   public boolean isOutOfDate(String fileName) {
212     String statusString = status(fileName);
213     if(statusString == nullreturn false;
214     char updateFlag = statusString.charAt(7);
215     if(DEBUGOut.prln(">>" + updateFlag + "<<");
216     if(DEBUGOut.prln(">>" + statusString + "<<");
217     if(updateFlag == '*')
218       return true;
219     else
220       return false;
221   // isOutOfDate()
222 
223   /**
224    * Use the repository's status command to figure out if the file is
225    * unknown.
226    @param fileName the file or directory to work on (should be relative
227    * to the repository's working directory, and use "/" as a path separator).
228    @return boolean giving status indication.
229    */
230   public boolean isUnknown(String fileName) {
231     String statusString = status(fileName);
232     if(DEBUGOut.prln(">>" + statusString + "<<");
233     if(DEBUGOut.prln(getCommandOutput());
234     if(statusString == null && getCommandStderr().indexOf("not a working copy">= 0)
235     //if(statusString == null && getCommandStderr().contains("not a working copy"))
236       return true;
237     else
238       return false;
239   // isUnknown()
240 
241   /**
242    * Check for the existence of a module (i.e. top-level directory).
243    @param moduleName directory to look for.
244    @return boolean giving status indication.
245    */
246   public boolean exists(String moduleName) {
247     List com = new ArrayList();
248     com.add(getCommandName());
249     com.add("ls");
250     com.add(getRoot() "/" + moduleName);
251     String[] comArray = (String[]) com.toArray(new String[com.size()]);
252     boolean result = runCommand(comArray);
253     return result;
254   // exists()
255 
256 // SvnRepository