0001: // CvsDirectory.java
0002: // $Id: CvsDirectory.java,v 1.66 2005/01/20 16:47:16 ylafon Exp $
0003: // (c) COPYRIGHT MIT and INRIA, 1997.
0004: // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006: package org.w3c.cvs;
0007:
0008: import java.util.Enumeration;
0009: import java.util.Hashtable;
0010: import java.util.Properties;
0011: import java.util.StringTokenizer;
0012:
0013: import java.io.DataInputStream;
0014: import java.io.File;
0015: import java.io.FileInputStream;
0016: import java.io.FilenameFilter;
0017: import java.io.FilterInputStream;
0018: import java.io.InputStream;
0019: import java.io.OutputStream;
0020: import java.io.PrintStream;
0021:
0022: import org.w3c.util.AsyncLRUList;
0023: import org.w3c.util.LRUAble;
0024: import org.w3c.util.LRUList;
0025:
0026: //
0027: // FIXME add extra environment parameter to all public methods
0028: // witch run cvs.
0029: //
0030:
0031: public class CvsDirectory implements LRUAble, CVS {
0032: /**
0033: * Property giving the path of the cvs binary.
0034: * This property should be set to the absolute path to the cvs command
0035: * in your local environment.
0036: * <p>This property defaults to <code>/usr/local/bin/cvs</code>.
0037: */
0038: public static final String CVSPATH_P = "org.w3c.cvs.path";
0039: /**
0040: * Property giving your CVS repository.
0041: * This property should be set to the absolute path of your repository.
0042: * <p>This property defaults to <code>/afs/w3.org/pub/WWW</code>.
0043: */
0044: public static final String CVSROOT_P = "org.w3c.cvs.root";
0045: /**
0046: * Property giving the path of the cvswrapper.
0047: * Because CVS can't run without being in the right directory, this
0048: * classes use a shell script wrapper to issue cvs commands, that will
0049: * change directory appropriately.
0050: * <p>You should have gotten this wrapper in the distribution
0051: * <code>bin</code> directory.
0052: * <p>This property defaults to
0053: * <code>/afs/w3.org/usr/abaird/Jigsaw/bin/cvs_wrapper</code>.
0054: */
0055: public final static String CVSWRAP_P = "org.w3c.cvs.wrapper";
0056:
0057: /**
0058: * The default CVS path.
0059: */
0060: public final static String cvspath_def = "/usr/local/bin/cvs";
0061: /**
0062: * The default CVS root path.
0063: */
0064: public final static String cvsroot_def = "/afs/w3.org/CVS-Repository";
0065: /**
0066: * The default CVS wrapper path.
0067: */
0068: public final static String cvswrap_def = "/afs/w3.org/usr/abaird/Jigsaw/bin/cvs_wrapper";
0069:
0070: /**
0071: * Our cache of existing CVS managers.
0072: * Maps absolute directory names to appropriate CvsDirectory instance.
0073: */
0074: protected static Hashtable cache = new Hashtable(23);
0075: /**
0076: * All CVS entries are LRU maintained too.
0077: */
0078: protected static LRUList lru = new AsyncLRUList();
0079: /**
0080: * Our recommended cache size.
0081: */
0082: protected static int cachesize = 32;
0083:
0084: /**
0085: * LRU management - previous entry.
0086: */
0087: protected LRUAble prev = null;
0088: /**
0089: * LRU management - next entry.
0090: */
0091: protected LRUAble next = null;
0092: /**
0093: * The time at which we last checked the cvs status of that directory.
0094: */
0095: protected long cvscheck_stamp = -1;
0096: /**
0097: * The time at which we last examined the repository for this directory.
0098: */
0099: protected long cvsrep_stamp = -1;
0100: /**
0101: * Has this directory manager been cleaned up (removed from cache).
0102: */
0103: protected boolean clean = true;
0104: /**
0105: * The directory we manage.
0106: */
0107: protected File directory = null;
0108: /**
0109: * The corresponding repository directory (when available).
0110: */
0111: protected File repdir = null;
0112: /**
0113: * Known CVS entries (files)
0114: */
0115: protected Hashtable entries = null;
0116: /**
0117: * Our associated CvsRunner.
0118: */
0119: protected CvsRunner runner = null;
0120: /**
0121: * The properties we use for initialization.
0122: */
0123: public Properties props = null;
0124:
0125: String cvspath = cvspath_def;
0126: String cvsroot = cvsroot_def;
0127: String cvswrapper[] = { cvswrap_def };
0128:
0129: /**
0130: * This one is the third copy of the same piece of code (!)
0131: * Parse the given prop value into an array of | separated components.
0132: * @param propval The property value (may be <strong>null</strong>).
0133: * @param def The default value (if undefined).
0134: * @return A String array, or <strong>null</strong>.
0135: */
0136:
0137: private static String[] parseArrayProperty(String propval) {
0138: if (propval == null)
0139: return null;
0140: // Parse the property value:
0141: StringTokenizer st = new StringTokenizer(propval, "|");
0142: int len = st.countTokens();
0143: String ret[] = new String[len];
0144: for (int i = 0; i < ret.length; i++) {
0145: ret[i] = st.nextToken();
0146: }
0147: return ret;
0148: }
0149:
0150: File computeRepositoryDirectory(File dir) {
0151: File rep = new File(new File(dir, "CVS"), "Repository");
0152: File ret = null;
0153: if (!rep.exists())
0154: return null;
0155: try {
0156: DataInputStream in = new DataInputStream(
0157: new FileInputStream(rep));
0158: String nm = in.readLine();
0159: if (nm.startsWith("/"))
0160: ret = new File(nm);
0161: else
0162: ret = new File(cvsroot, nm);
0163: in.close();
0164: } catch (Exception ex) {
0165: return null;
0166: }
0167: return ret;
0168: }
0169:
0170: protected String[] getCvsWrapper() {
0171: return cvswrapper;
0172: }
0173:
0174: protected String[] getCvsDefaults() {
0175: String ret[] = new String[6];
0176: ret[0] = "-directory";
0177: ret[1] = getDirectory().getAbsolutePath();
0178: ret[2] = cvspath;
0179: ret[3] = "-q";
0180: ret[4] = "-d";
0181: ret[5] = cvsroot;
0182: return ret;
0183: }
0184:
0185: protected synchronized void createFileEntry(long timestamp,
0186: String name, int status) {
0187: if (entries == null)
0188: entries = new Hashtable(13);
0189: CvsEntry entry = new CvsEntry(this , timestamp, name, false,
0190: status);
0191: entries.put(name, entry);
0192: }
0193:
0194: protected synchronized void createDirectoryEntry(long timestamp,
0195: String name, int status) {
0196: if (entries == null)
0197: entries = new Hashtable(13);
0198: CvsEntry entry = new CvsEntry(this , timestamp, name, true,
0199: status);
0200: entries.put(name, entry);
0201: }
0202:
0203: public static Properties defprops = null;
0204:
0205: /**
0206: * Get a CvsDirectory.
0207: * @param directory The CVS directory.
0208: * @param props The cvs properties.
0209: * @param cvspath The absolute path of the cvs program.
0210: * @param cvsroot The absolute path of the CVS repository.
0211: * @param cvswrap The absolute path of the cvs wrapper program
0212: * @return A CvsDirectory instance.
0213: * @exception CvsException If some initialisation failed
0214: */
0215: public static synchronized CvsDirectory getManager(File directory,
0216: Properties props, String cvspath, String cvsroot,
0217: String cvswrap[]) throws CvsException {
0218: // Initialize default properties if not done yet:
0219: if (defprops == null)
0220: defprops = System.getProperties();
0221: String abspath = directory.getAbsolutePath();
0222: // Check the cache first:
0223: CvsDirectory cvs = (CvsDirectory) cache.get(abspath);
0224: if (cvs != null) {
0225: cvs.cacheLoaded();
0226: return cvs;
0227: }
0228: // Create a new cache entry for that directory and add to cache:
0229: cvs = new CvsDirectory(directory, ((props == null) ? defprops
0230: : props), cvspath, cvsroot, cvswrap);
0231: if (cache.size() >= cachesize)
0232: cacheUnload();
0233: cache.put(abspath, cvs);
0234: lru.toHead(cvs);
0235: return cvs;
0236: }
0237:
0238: /**
0239: * Get a CvsDirectory.
0240: * @param directory The CVS directory
0241: * @return A CvsDirectory instance.
0242: * @exception CvsException If some initialisation failed
0243: */
0244: public static CvsDirectory getManager(File directory)
0245: throws CvsException {
0246: return getManager(directory, null, null, null, null);
0247: }
0248:
0249: /**
0250: * @param directory The CVS directory.
0251: * @param props The cvs properties.
0252: * @return A CvsDirectory instance.
0253: * @exception CvsException If some initialisation failed
0254: */
0255: public static CvsDirectory getManager(File directory,
0256: Properties props) throws CvsException {
0257: return getManager(directory, props, null, null, null);
0258: }
0259:
0260: /**
0261: * @param father The father CvsDirectory.
0262: * @param directory The CVS directory.
0263: * @return A CvsDirectory instance.
0264: * @exception CvsException If some initialisation failed
0265: */
0266: protected static CvsDirectory getManager(CvsDirectory father,
0267: File dir) throws CvsException {
0268: return getManager(dir, father.props, null, null, null);
0269: }
0270:
0271: /**
0272: * LRU management - Get next node.
0273: * @return A CvsDirectory instance.
0274: */
0275:
0276: public LRUAble getNext() {
0277: return next;
0278: }
0279:
0280: /**
0281: * LRU management - Get previous node.
0282: * @return A CvsDirectory instance.
0283: */
0284:
0285: public LRUAble getPrev() {
0286: return prev;
0287: }
0288:
0289: /**
0290: * LRU management - Set next node.
0291: * @return A CvsDirectory instance.
0292: */
0293:
0294: public void setNext(LRUAble next) {
0295: this .next = next;
0296: }
0297:
0298: /**
0299: * LRU management - Set previous node.
0300: * @return A CvsDirectory instance.
0301: */
0302:
0303: public void setPrev(LRUAble prev) {
0304: this .prev = prev;
0305: }
0306:
0307: public static String statusToString(int st) {
0308: return (((st > 0) && (st < status.length)) ? status[st]
0309: : "unknown");
0310: }
0311:
0312: /**
0313: * This directory manager is being fetched from the cache.
0314: * Perform any action before we return it back to the user.
0315: * @exception CvsException If some CVS action fails during
0316: * reinitialization.
0317: */
0318:
0319: protected void cacheLoaded() throws CvsException {
0320: lru.toHead(this );
0321: }
0322:
0323: /**
0324: * Remove a directory manager from the cache.
0325: * Clear al references to other objects in order to free up memory
0326: * even if the caller maintains a pointer to the manager.
0327: */
0328:
0329: protected static synchronized void cacheUnload() {
0330: // Pick the manager to remove:
0331: CvsDirectory cvs = (CvsDirectory) lru.removeTail();
0332: // Clean it up:
0333: if (cvs != null) {
0334: cvs.entries = null;
0335: cvs.clean = true;
0336: cvs.cvsrep_stamp = -1;
0337: cvs.cvscheck_stamp = -1;
0338: cache.remove(cvs.getDirectory().getAbsolutePath());
0339: }
0340: }
0341:
0342: /**
0343: * Look for a file entry.
0344: * @param filename The name of the entry to look for.
0345: */
0346:
0347: protected CvsEntry getFileEntry(String filename) {
0348: return (entries != null) ? (CvsEntry) entries.get(filename)
0349: : null;
0350: }
0351:
0352: protected void removeFileEntry(String filename) {
0353: if (entries != null)
0354: entries.remove(filename);
0355: }
0356:
0357: /**
0358: * Look for a sub-directory entry.
0359: * @param filename The name of the entry to look for.
0360: */
0361:
0362: protected CvsEntry getDirectoryEntry(String filename) {
0363: return (entries != null) ? (CvsEntry) entries.get(filename)
0364: : null;
0365: }
0366:
0367: /**
0368: * Refresh the file entries for that directory.
0369: * @exception CvsException If the underlying CVS command failed.
0370: */
0371:
0372: public void refresh() throws CvsException {
0373: synchronized (this ) {
0374: LoadUpdateHandler handler = new LoadUpdateHandler(this );
0375: CvsStatusHandler statush = new CvsStatusHandler(this );
0376: try {
0377: entries = null; //FIXME other effect?
0378: runner.cvsLoad(this , handler, statush);
0379: } catch (CvsException ex) {
0380: clean = true;
0381: entries = null;
0382: throw ex;
0383: }
0384: clean = false;
0385: cvscheck_stamp = getDirectory().lastModified();
0386: handler.notifyEnd();
0387: //must be called after UpdateHandler
0388: statush.notifyEnd();
0389: }
0390: lru.toHead(this );
0391: }
0392:
0393: /**
0394: * Refresh the file entries for that filename.
0395: * @exception CvsException If the underlying CVS command failed.
0396: */
0397: protected void refresh(String filename) throws CvsException {
0398: synchronized (this ) {
0399: LoadUpdateHandler handler = new LoadUpdateHandler(this );
0400: CvsStatusHandler statush = new CvsStatusHandler(this );
0401:
0402: runner.cvsLoad(this , filename, handler, statush);
0403:
0404: handler.notifyEnd();
0405: //must be called after UpdateHandler
0406: statush.notifyEnd();
0407: }
0408: lru.toHead(this );
0409: }
0410:
0411: /**
0412: * Refresh the file entry status for that filename.
0413: * @exception CvsException If the underlying CVS command failed.
0414: */
0415: protected void refreshStatus(String filename) throws CvsException {
0416: synchronized (this ) {
0417: LoadUpdateHandler handler = new LoadUpdateHandler(this );
0418: runner.cvsLoad(this , filename, handler);
0419: handler.notifyEnd();
0420: }
0421: lru.toHead(this );
0422: }
0423:
0424: /**
0425: * Refresh the file entry revision number for that filename.
0426: * @exception CvsException If the underlying CVS command failed.
0427: */
0428: protected void refreshRevision(String filename) throws CvsException {
0429: synchronized (this ) {
0430: CvsStatusHandler statush = new CvsStatusHandler(this );
0431: runner.cvsStatus(this , filename, statush);
0432: statush.notifyEnd();
0433: }
0434: }
0435:
0436: /**
0437: * This directory manager is about to be used, check it.
0438: * @exception CvsException If some CVS error occurs in that process.
0439: */
0440:
0441: protected synchronized void checkUse() throws CvsException {
0442: if (clean) {
0443: // This has been cleaned up some times ago, restore:
0444: if (cache.size() >= cachesize)
0445: cacheUnload();
0446: cacheLoaded();
0447: cache.put(getDirectory().getAbsolutePath(), this );
0448: clean = false;
0449: }
0450: // Check if update is needed:
0451: if (needsUpdate())
0452: refresh();
0453: }
0454:
0455: /**
0456: * That file in the directory is about to be used, check its status.
0457: * @param filename The name of the entry that is about to be used.
0458: * @exception CvsException If a CVS error occurs.
0459: */
0460:
0461: protected synchronized void checkUse(String filename)
0462: throws CvsException {
0463: CvsEntry entry = getFileEntry(filename);
0464: if ((entry == null) || entry.needsUpdate())
0465: refresh();
0466: }
0467:
0468: /**
0469: * This directory manager is about to be used for sub-directories.
0470: * @exception CvsException If a CVS error occurs.
0471: */
0472: protected synchronized void checkDirectoryUse() throws CvsException {
0473: //test new thing
0474: //runner.cvsUpdateDirectories(this, null);
0475:
0476: // Can we gain access to the repository ?
0477: if (repdir == null) {
0478: if ((repdir = computeRepositoryDirectory(getDirectory())) == null)
0479: throw new CvsException("Repository not accessible.");
0480: }
0481: // Are we uptodate against repository ?
0482: if (cvsrep_stamp < repdir.lastModified()) {
0483: long stamp = System.currentTimeMillis();
0484: // Get all subdirs from repository:
0485: String subdirs[] = repdir.list(new DirectoryFilter());
0486: if (subdirs != null) {
0487: for (int i = 0; i < subdirs.length; i++) {
0488: File subdir = new File(getDirectory(), subdirs[i]);
0489: if (subdir.exists())
0490: createDirectoryEntry(stamp, subdirs[i], DIR_CO);
0491: else
0492: createDirectoryEntry(stamp, subdirs[i], DIR_NCO);
0493: }
0494: }
0495: // Check against all local sub-directories:
0496: subdirs = getDirectory().list(new DirectoryFilter());
0497: if (subdirs != null) {
0498: for (int i = 0; i < subdirs.length; i++) {
0499: if (getDirectoryEntry(subdirs[i]) == null)
0500: createDirectoryEntry(stamp, subdirs[i], DIR_Q);
0501: }
0502: }
0503: cvsrep_stamp = stamp;
0504: }
0505: }
0506:
0507: /**
0508: * This directory manager is about to be used for the given sub-directory.
0509: * (Really really faster than checkDirectoryUse())
0510: * @exception CvsException If a CVS error occurs.
0511: */
0512: protected synchronized void checkDirectoryUse(String subdir)
0513: throws CvsException {
0514: // Can we gain access to the repository ?
0515: if (repdir == null) {
0516: if ((repdir = computeRepositoryDirectory(getDirectory())) == null)
0517: throw new CvsException("Repository not accessible.");
0518: }
0519: // Are we uptodate against repository ?
0520: if (cvsrep_stamp < repdir.lastModified()) {
0521: long stamp = System.currentTimeMillis();
0522: File dir = new File(repdir, subdir);
0523: if (dir.exists()) {
0524: File subd = new File(getDirectory(), subdir);
0525: if (subd.exists())
0526: createDirectoryEntry(stamp, subdir, DIR_CO);
0527: else
0528: createDirectoryEntry(stamp, subdir, DIR_NCO);
0529: } else {
0530: createDirectoryEntry(stamp, subdir, DIR_Q);
0531: }
0532: }
0533: }
0534:
0535: /**
0536: * Does this directory needs some CVS update ?
0537: */
0538:
0539: protected boolean needsUpdate() {
0540: // Has the directory changed since we last visited it ?
0541: if (cvscheck_stamp < directory.lastModified()) {
0542: return true;
0543: }
0544: // Has any entry changed since its last status ?
0545: if (entries != null) {
0546: Enumeration e = entries.elements();
0547: while (e.hasMoreElements()) {
0548: CvsEntry entry = (CvsEntry) e.nextElement();
0549: if (entry.needsUpdate()) {
0550: return true;
0551: }
0552: }
0553: }
0554: return false;
0555: }
0556:
0557: /**
0558: * List all available file entries in that directory.
0559: * This method will list all possible files:
0560: * <ul><li>The ones that exist but are not in the repository.
0561: * <li>The ones that are in the repository but not in local space.
0562: * <li>All the other ones.
0563: * </ul>
0564: * @return An enumeration listing zero or more String instances.
0565: * @exception CvsException If some CVS error occured while examining
0566: * the cvs status of entries.
0567: */
0568:
0569: public Enumeration listFiles() throws CvsException {
0570: lru.toHead(this );
0571: checkUse();
0572: return new FileEnumeration(entries);
0573: }
0574:
0575: /**
0576: * List available sub-directories of that directory.
0577: * This method will list of possible directories. If access to the
0578: * repository is permitted, it will look into that to get a list of
0579: * unchecked out directories, otherwise, it will just list the
0580: * checked out ones.
0581: * @return An enumeration listing zero or more File instances.
0582: * @exception CvsException If some CVS error occured while examining
0583: * the cvs status of entries.
0584: */
0585:
0586: public Enumeration listDirectories() throws CvsException {
0587: lru.toHead(this );
0588: checkDirectoryUse();
0589: return new DirectoryEnumeration(entries);
0590: }
0591:
0592: /**
0593: * Get the status of a file entry.
0594: * @param filename The file whose status is to be fetched.
0595: * @param refresh Should we refresh the status?
0596: * @return A integer status indicating the CVS status of that file within
0597: * the repository.
0598: * @exception CvsException If some CVS error occured while examining
0599: * the cvs status of entries.
0600: */
0601: public int status(String filename, boolean refresh)
0602: throws CvsException {
0603: if (refresh)
0604: refreshStatus(filename);
0605: return status(filename);
0606: }
0607:
0608: /**
0609: * Get the status of a file entry.
0610: * @param filename The file whose status is to be fetched.
0611: * @return A integer status indicating the CVS status of that file within
0612: * the repository.
0613: * @exception CvsException If some CVS error occured while examining
0614: * the cvs status of entries.
0615: */
0616: public int status(String filename) throws CvsException {
0617: lru.toHead(this );
0618: checkUse(filename);
0619: CvsEntry entry = (entries != null) ? (CvsEntry) entries
0620: .get(filename) : null;
0621: if (entry == null) {
0622: //let's make a try with the filename in update
0623: refresh(filename);
0624: entry = (entries != null) ? (CvsEntry) entries
0625: .get(filename) : null;
0626: if (entry == null)
0627: throw new CvsException(filename + ": no such entry.");
0628: }
0629: return entry.getStatus();
0630: }
0631:
0632: /**
0633: * Get the revision number of the given file.
0634: * @param filename The File name
0635: * @return A String instance
0636: * @exception CvsException if some CVS errors occurs
0637: */
0638: public String revision(String filename) throws CvsException {
0639: lru.toHead(this );
0640: checkUse(filename);
0641: CvsEntry entry = (entries != null) ? (CvsEntry) entries
0642: .get(filename) : null;
0643: if (entry == null) {
0644: //let's make a try with the filename in update
0645: refresh(filename);
0646: entry = (entries != null) ? (CvsEntry) entries
0647: .get(filename) : null;
0648: if (entry == null)
0649: throw new CvsException(filename + ": no such entry.");
0650: } else if ((entry.getRevision() == null)
0651: && (entry.getStatus() != FILE_Q)) {
0652: refreshRevision(filename);
0653: }
0654: return entry.getRevision();
0655: }
0656:
0657: /**
0658: * Get the Sticky Options of the given file.
0659: * @param filename The File name
0660: * @return A String instance
0661: * @exception CvsException if some CVS errors occurs
0662: */
0663: public String stickyOptions(String filename) throws CvsException {
0664: lru.toHead(this );
0665: checkUse(filename);
0666: CvsEntry entry = (entries != null) ? (CvsEntry) entries
0667: .get(filename) : null;
0668: if (entry == null) {
0669: //let's make a try with the filename in update
0670: refresh(filename);
0671: entry = (entries != null) ? (CvsEntry) entries
0672: .get(filename) : null;
0673: if (entry == null)
0674: throw new CvsException(filename + ": no such entry.");
0675: } else if ((entry.getRevision() == null)
0676: && (entry.getStatus() != FILE_Q)) {
0677: refreshRevision(filename);
0678: }
0679: return entry.getStickyOptions();
0680: }
0681:
0682: /**
0683: * Update these files from the repository.
0684: * @param files The name of the files to update (as a String array).
0685: * @exception CvsException If CVS process failed.
0686: */
0687:
0688: public void update(String files[]) throws CvsException {
0689: lru.toHead(this );
0690: // No need to checkUse here:
0691: CvsUpdateHandler handler = new CvsUpdateHandler(this );
0692: runner.cvsUpdate(this , files, handler);
0693: }
0694:
0695: /**
0696: * Update this file from the repository.
0697: * @param file The name of the file to update (as a String).
0698: * @exception CvsException If CVS process failed.
0699: */
0700: public void update(String file) throws CvsException {
0701: String files[] = new String[1];
0702: files[0] = file;
0703: update(files);
0704: }
0705:
0706: /**
0707: * Update all that directory's content. (not recursivly).
0708: * @exception CvsException If some CVS error occured during update.
0709: */
0710:
0711: public void update() throws CvsException {
0712: lru.toHead(this );
0713: CvsUpdateHandler handler = new CvsUpdateHandler(this );
0714: runner.cvsUpdate(this , handler);
0715: }
0716:
0717: /**
0718: * Update thes files matching the given regular expression from the
0719: * repository.
0720: * @param files The name of the files to update (as a String array).
0721: * @exception CvsException If CVS process failed.
0722: */
0723: public void updateRegexp(String regexp) throws CvsException {
0724: update(regexp);
0725: }
0726:
0727: /**
0728: * Perform a cvs get
0729: * @param path the file (or directory) path
0730: * @exception CvsException If CVS process failed.
0731: */
0732: public void get(String path) throws CvsException {
0733: lru.toHead(this );
0734: runner.cvsGet(this , path);
0735: }
0736:
0737: /**
0738: * Commit pending actions on given file.
0739: * @param names The name of the files to commit.
0740: * @param msg The associated message.
0741: * @param env The extra env to use during commit.
0742: * @exception CvsException If some error occured during the CVS process.
0743: */
0744: public void commit(String names[], String msg, String env[])
0745: throws CvsException {
0746: lru.toHead(this );
0747: // We don't really need to check use here.
0748: CvsCommitHandler handler = new CvsCommitHandler(this );
0749: runner.cvsCommit(this , names, msg, handler, env);
0750: }
0751:
0752: /**
0753: * Commit pending actions on given file.
0754: * @param file The file to commit.
0755: * @param msg The associated message.
0756: * @param env The extra env to use during commit.
0757: * @exception CvsException If some error occured during the CVS process.
0758: */
0759: public void commit(String file, String msg, String env[])
0760: throws CvsException {
0761: lru.toHead(this );
0762: String names[] = new String[1];
0763: names[0] = file;
0764: commit(names, msg, env);
0765: }
0766:
0767: /**
0768: * Commit pending actions on given file.
0769: * @param names The name of the files to commit.
0770: * @param msg The associated message.
0771: * @exception CvsException If some error occured during the CVS process.
0772: */
0773: public void commit(String names[], String msg) throws CvsException {
0774: lru.toHead(this );
0775: // We don't really need to check use here.
0776: CvsCommitHandler handler = new CvsCommitHandler(this );
0777: runner.cvsCommit(this , names, msg, handler);
0778: }
0779:
0780: /**
0781: * Commit pending actions on given file.
0782: * @param file The file to commit.
0783: * @param msg The associated message.
0784: * @exception CvsException If some error occured during the CVS process.
0785: */
0786: public void commit(String file, String msg) throws CvsException {
0787: String names[] = new String[1];
0788: names[0] = file;
0789: commit(names, msg);
0790: }
0791:
0792: /**
0793: * Commit pending actions to all that directory content.
0794: * @param msg The associated message.
0795: * @exception CvsException If some CVS error occurs during the CVS process.
0796: */
0797:
0798: public void commit(String msg) throws CvsException {
0799: lru.toHead(this );
0800: // No need to checkUse
0801: CvsCommitHandler handler = new CvsCommitHandler(this );
0802: runner.cvsCommit(this , msg, handler);
0803: }
0804:
0805: /**
0806: * Commit pending actions to all that directory content.
0807: * @param msg The associated message.
0808: * @param env The extra environment.
0809: * @exception CvsException If some CVS error occurs during the CVS process.
0810: */
0811:
0812: public void commit(String msg, String env[]) throws CvsException {
0813: lru.toHead(this );
0814: // No need to checkUse
0815: CvsCommitHandler handler = new CvsCommitHandler(this );
0816: runner.cvsCommit(this , msg, handler, env);
0817: }
0818:
0819: /**
0820: * Commit pending actions on files matching the given regular expression.
0821: * @param regexp The regular expresion.
0822: * @param msg The associated message.
0823: * @param env The extra env to use during commit.
0824: * @exception CvsException If some error occured during the CVS process.
0825: */
0826: public void commitRegexp(String regexp, String comment,
0827: String env[]) throws CvsException {
0828: commit(regexp, comment, env);
0829: }
0830:
0831: /**
0832: * Revert the file, make the given revision the current one.
0833: * <UL><LI>First remove the file</LI>
0834: * <LI>perform a cvs update -p -r <revision></LI>
0835: * @param filename The name of the file to revert.
0836: * @param revision The revision number to get.
0837: * @param msg The associated message.
0838: * @param env The extra environment.
0839: * @exception CvsException If some CVS error occurs during the CVS process.
0840: */
0841: public void revert(String filename, String revision, String msg,
0842: String env[]) throws CvsException {
0843: File file = new File(getDirectory(), filename);
0844: if (!file.exists())
0845: throw new CvsException("the file " + file
0846: + " can't be reverted : " + "it doesn't exists!");
0847: // 1: remove the file
0848: file.delete();
0849: String names[] = new String[1];
0850: names[0] = filename;
0851: // 2: revert
0852: runner.cvsRevert(this , filename, revision, file, env);
0853: // done!
0854: }
0855:
0856: /**
0857: * Revert the file, make the given revision the current one.
0858: * <UL><LI>First remove the file</LI>
0859: * <LI>perform a cvs update -p -r <revision></LI>
0860: * @param filename The name of the file to revert.
0861: * @param revision The revision number to get.
0862: * @param out The output stream. (reverted file will be written in)
0863: * @param env The extra environment.
0864: * @exception CvsException If some CVS error occurs during the CVS process.
0865: */
0866: public void revert(String filename, OutputStream out,
0867: String revision, String env[]) throws CvsException {
0868: runner.cvsRevert(this , filename, revision, out, env);
0869: }
0870:
0871: /**
0872: * Get the log associated to the given file.
0873: * @param filename The name of the file whose log is to be fetched.
0874: * @exception CvsException If some CVS error occurs in the process.
0875: */
0876:
0877: public String log(String filename) throws CvsException {
0878: lru.toHead(this );
0879: // No need to checkUse here
0880: return runner.cvsLog(this , filename);
0881: }
0882:
0883: /**
0884: * Get the diff of given file against repository.
0885: * @param filename The name of the file to diff.
0886: * @return The diffs has a String, or <strong>null</strong> if the file
0887: * is in sync with the repository.
0888: * @exception CvsException If some CVS exception occurs within the
0889: * process.
0890: */
0891:
0892: public String diff(String filename) throws CvsException {
0893: lru.toHead(this );
0894: checkUse(filename);
0895: CvsEntry entry = getFileEntry(filename);
0896: // Spare a cvs command when possible:
0897: if ((entry != null) && (!entry.needsUpdate())
0898: && (entry.getStatus() == FILE_OK))
0899: return null;
0900: // Have to run the command:
0901: return runner.cvsDiff(this , filename);
0902: }
0903:
0904: /**
0905: * Add the given file to the CVS repository.
0906: * The addition will have to be commited through a commit of the same
0907: * file before taking effect.
0908: * @param names The name of the files to add.
0909: * @exception CvsException If some CVS error occurs during the process.
0910: */
0911:
0912: public void add(String names[]) throws CvsException {
0913: add(names, null);
0914: }
0915:
0916: /**
0917: * Add the given file to the CVS repository.
0918: * The addition will have to be commited through a commit of the same
0919: * file before taking effect.
0920: * @param names The name of the files to add.
0921: * @param env The extra env to use during the process.
0922: * @exception CvsException If some CVS error occurs during the process.
0923: */
0924: public void add(String names[], String env[]) throws CvsException {
0925: lru.toHead(this );
0926: // No need to checkUse here:
0927: long stamp = System.currentTimeMillis();
0928: runner.cvsAdd(this , names, env);
0929: // Update all files status:
0930: for (int i = 0; i < names.length; i++) {
0931: CvsEntry entry = getFileEntry(names[i]);
0932: if (entry != null)
0933: entry.setStatus(stamp, FILE_A);
0934: else
0935: createFileEntry(stamp, names[i], FILE_A);
0936: }
0937: }
0938:
0939: /**
0940: * Add the file matching the given regular expression to the CVS
0941: * repository.
0942: * The addition will have to be commited through a commit of the same
0943: * file before taking effect.
0944: * @param regexp The regular expression.
0945: * @param env The extra env to use during the process.
0946: * @exception CvsException If some CVS error occurs during the process.
0947: */
0948: public void addRegexp(String regexp, String env[])
0949: throws CvsException {
0950: lru.toHead(this );
0951: String files[] = new String[1];
0952: files[0] = regexp;
0953: runner.cvsAdd(this , files, env);
0954: refresh();
0955: }
0956:
0957: /**
0958: * Remove the given file from the repository.
0959: * @param names The files to be removed.
0960: * @exception CvsException If some CVS error occurs during that process.
0961: */
0962:
0963: public void remove(String names[], String msg, String env[])
0964: throws CvsException {
0965: lru.toHead(this );
0966: // No need to check use here:
0967: long stamp = System.currentTimeMillis();
0968: runner.cvsRemove(this , names);
0969: //commit the remove
0970: commit(names, msg, env);
0971: // Update all files status:
0972: for (int i = 0; i < names.length; i++) {
0973: removeFileEntry(names[i]);
0974: }
0975: // for (int i = 0 ; i < names.length; i++) {
0976: // CvsEntry entry = getFileEntry(names[i]);
0977: // if ( entry != null )
0978: // entry.setStatus(stamp, FILE_R);
0979: // else
0980: // createFileEntry(stamp, names[i], FILE_R);
0981: // }
0982: }
0983:
0984: /**
0985: * Perform a RCS request.
0986: * @param command the rcs command splitted in a string array.
0987: * @exception CvsException If some CVS error occurs during that process.
0988: */
0989: public void admin(String command[]) throws CvsException {
0990: lru.toHead(this );
0991: runner.cvsAdmin(this , command);
0992: }
0993:
0994: /**
0995: * Display the status of the entries in that directory.
0996: * @param prt A print stream to print to.
0997: */
0998:
0999: public void display(PrintStream prt) {
1000: lru.toHead(this );
1001: try {
1002: Enumeration files = listFiles();
1003: while (files.hasMoreElements()) {
1004: String name = (String) files.nextElement();
1005: int stat = status(name);
1006: prt.println(name + ": " + status[stat]);
1007: }
1008: } catch (CvsException ex) {
1009: prt.println("*** CVS Error: " + ex.getMessage());
1010: }
1011: }
1012:
1013: /**
1014: * Get a sub-directory status.
1015: * @param subdir The name of the subdirectory.
1016: * @return An integer CVS status for the given sub-directory.
1017: * @exception CvsException if the CVS process failed.
1018: */
1019:
1020: public int getDirectoryStatus(String subdir) throws CvsException {
1021: return getDirectoryStatus(subdir, true);
1022: }
1023:
1024: /**
1025: * Get a sub-directory status.
1026: * @param subdir The name of the subdirectory.
1027: * @param update If true update all directory entries.
1028: * @return An integer CVS status for the given sub-directory.
1029: * @exception CvsException if the CVS process failed.
1030: */
1031: public int getDirectoryStatus(String subdir, boolean update)
1032: throws CvsException {
1033: lru.toHead(this );
1034: if (update)
1035: checkDirectoryUse();
1036: else
1037: checkDirectoryUse(subdir);
1038: CvsEntry entry = getDirectoryEntry(subdir);
1039: return (entry == null) ? DIR_Q : entry.getStatus();
1040: }
1041:
1042: /**
1043: * Check out, or update a sub-directory.
1044: * @param subdir The sub directory to update.
1045: * @exception CvsException If the CVS process failed.
1046: */
1047:
1048: public void updateDirectory(String subdir) throws CvsException {
1049: lru.toHead(this );
1050: // Check use of the directories:
1051: checkDirectoryUse();
1052: // Run the command:
1053: CvsEntry entry = getDirectoryEntry(subdir);
1054: if (entry == null)
1055: throw new CvsException("Unknown subdirectory " + subdir);
1056: DirectoryUpdateHandler handler = new DirectoryUpdateHandler(
1057: this );
1058: runner.cvsUpdateDirectory(this , entry.file, handler);
1059: // Mark the new entry state:
1060: entry.setStatus(handler.stamp, DIR_CO);
1061: }
1062:
1063: /**
1064: * Get the directory controlled by this manager.
1065: * @return A File instance locating the directory.
1066: */
1067:
1068: public File getDirectory() {
1069: return directory;
1070: }
1071:
1072: /**
1073: * Create a new CVS manager for the given directory.
1074: * @param directory The directory for which a manager is to be created.
1075: * @param props The cvs properties.
1076: * @param cvspath The absolute path of the cvs program.
1077: * @param cvsroot The absolute path of the CVS repository.
1078: * @param cvswrap The absolute path of the cvs wrapper program
1079: * @exception CvsException If some initialisation failed
1080: */
1081:
1082: protected CvsDirectory(File directory, Properties props,
1083: String cvspath, String cvsroot, String cvswrap[])
1084: throws CvsException {
1085: if (!directory.exists())
1086: throw new UncheckedOutException("Unchecked out directory: "
1087: + directory.getAbsolutePath());
1088: this .props = props;
1089: this .cvspath = ((cvspath == null) ? props.getProperty(
1090: CVSPATH_P, cvspath_def) : cvspath);
1091: this .cvsroot = ((cvsroot == null) ? props.getProperty(
1092: CVSROOT_P, cvsroot_def) : cvsroot);
1093: this .cvswrapper = ((cvswrap == null) ? parseArrayProperty(props
1094: .getProperty(CVSWRAP_P, cvswrap_def)) : cvswrap);
1095: this .directory = directory;
1096: this .cvscheck_stamp = -1;
1097: this .runner = new CvsRunner();
1098: }
1099:
1100: public static void usage() {
1101: System.out.println("CvsDirectory <dir> [command] [files]");
1102: System.exit(1);
1103: }
1104:
1105: public static void main(String args[]) {
1106: String command = null;
1107: String params[] = null;
1108: File target = null;
1109:
1110: // Parse command line:
1111: switch (args.length) {
1112: case 0:
1113: usage();
1114: break;
1115: case 1:
1116: target = new File(args[0]);
1117: break;
1118: case 2:
1119: target = new File(args[0]);
1120: command = args[1];
1121: break;
1122: default:
1123: target = new File(args[0]);
1124: command = args[1];
1125: params = new String[args.length - 2];
1126: System.arraycopy(args, 2, params, 0, args.length - 2);
1127: break;
1128: }
1129: // Load the directory and perform command:
1130: try {
1131: CvsDirectory cvs = CvsDirectory
1132: .getManager(new File(args[0]));
1133: if (command == null) {
1134: cvs.display(System.out);
1135: } else if (command.equals("update")) {
1136: if (params != null)
1137: cvs.update(params);
1138: else
1139: cvs.update();
1140: } else if (command.equals("status")) {
1141: if (params.length != 1)
1142: usage();
1143: System.out.println(status[cvs.status(params[0])]);
1144: } else if (command.equals("diff")) {
1145: if (params.length != 1)
1146: usage();
1147: System.out.println(cvs.diff(params[0]));
1148: } else if (command.equals("log")) {
1149: if (params.length != 1)
1150: usage();
1151: System.out.println(cvs.log(params[0]));
1152: } else if (command.equals("add")) {
1153: if (params.length == 0)
1154: usage();
1155: cvs.add(params);
1156: } else if (command.equals("listdir")) {
1157: Enumeration e = cvs.listDirectories();
1158: while (e.hasMoreElements()) {
1159: String subdir = (String) e.nextElement();
1160: System.out.println(subdir + ": "
1161: + status[cvs.getDirectoryStatus(subdir)]);
1162: }
1163: } else if (command.equals("updatedir")) {
1164: if (params.length == 0)
1165: usage();
1166: cvs.updateDirectory(params[0]);
1167: } else {
1168: System.err.println("Unknown command [" + command + "]");
1169: }
1170: } catch (Exception ex) {
1171: ex.printStackTrace();
1172: }
1173: }
1174:
1175: }
|