예제 #1
0
파일: DirCache.java 프로젝트: alexkli/jgit
 /**
  * Unlock this file and abort this change.
  *
  * <p>The temporary file (if created) is deleted before returning.
  */
 public void unlock() {
   final LockFile tmp = myLock;
   if (tmp != null) {
     myLock = null;
     tmp.unlock();
   }
 }
예제 #2
0
파일: DirCache.java 프로젝트: alexkli/jgit
  void writeTo(final OutputStream os) throws IOException {
    final MessageDigest foot = Constants.newMessageDigest();
    final DigestOutputStream dos = new DigestOutputStream(os, foot);

    boolean extended = false;
    for (int i = 0; i < entryCnt; i++) extended |= sortedEntries[i].isExtended();

    // Write the header.
    //
    final byte[] tmp = new byte[128];
    System.arraycopy(SIG_DIRC, 0, tmp, 0, SIG_DIRC.length);
    NB.encodeInt32(tmp, 4, extended ? 3 : 2);
    NB.encodeInt32(tmp, 8, entryCnt);
    dos.write(tmp, 0, 12);

    // Write the individual file entries.

    final int smudge_s;
    final int smudge_ns;
    if (myLock != null) {
      // For new files we need to smudge the index entry
      // if they have been modified "now". Ideally we'd
      // want the timestamp when we're done writing the index,
      // so we use the current timestamp as a approximation.
      myLock.createCommitSnapshot();
      snapshot = myLock.getCommitSnapshot();
      smudge_s = (int) (snapshot.lastModified() / 1000);
      smudge_ns = ((int) (snapshot.lastModified() % 1000)) * 1000000;
    } else {
      // Used in unit tests only
      smudge_ns = 0;
      smudge_s = 0;
    }

    // Check if tree is non-null here since calling updateSmudgedEntries
    // will automatically build it via creating a DirCacheIterator
    final boolean writeTree = tree != null;

    if (repository != null && entryCnt > 0) updateSmudgedEntries();

    for (int i = 0; i < entryCnt; i++) {
      final DirCacheEntry e = sortedEntries[i];
      if (e.mightBeRacilyClean(smudge_s, smudge_ns)) e.smudgeRacilyClean();
      e.write(dos);
    }

    if (writeTree) {
      final TemporaryBuffer bb = new TemporaryBuffer.LocalFile();
      tree.write(tmp, bb);
      bb.close();

      NB.encodeInt32(tmp, 0, EXT_TREE);
      NB.encodeInt32(tmp, 4, (int) bb.length());
      dos.write(tmp, 0, 8);
      bb.writeTo(dos, null);
    }
    writeIndexChecksum = foot.digest();
    os.write(writeIndexChecksum);
    os.close();
  }
예제 #3
0
파일: DirCache.java 프로젝트: alexkli/jgit
 /**
  * Commit this change and release the lock.
  *
  * <p>If this method fails (returns false) the lock is still released.
  *
  * @return true if the commit was successful and the file contains the new data; false if the
  *     commit failed and the file remains with the old data.
  * @throws IllegalStateException the lock is not held.
  */
 public boolean commit() {
   final LockFile tmp = myLock;
   requireLocked(tmp);
   myLock = null;
   if (!tmp.commit()) return false;
   snapshot = tmp.getCommitSnapshot();
   if (indexChangedListener != null && !Arrays.equals(readIndexChecksum, writeIndexChecksum))
     indexChangedListener.onIndexChanged(new IndexChangedEvent());
   return true;
 }
예제 #4
0
파일: DirCache.java 프로젝트: alexkli/jgit
 /**
  * Try to establish an update lock on the cache file.
  *
  * @return true if the lock is now held by the caller; false if it is held by someone else.
  * @throws IOException the output file could not be created. The caller does not hold the lock.
  */
 public boolean lock() throws IOException {
   if (liveFile == null) throw new IOException(JGitText.get().dirCacheDoesNotHaveABackingFile);
   final LockFile tmp = new LockFile(liveFile, fs);
   if (tmp.lock()) {
     tmp.setNeedStatInformation(true);
     myLock = tmp;
     return true;
   }
   return false;
 }
예제 #5
0
파일: DirCache.java 프로젝트: alexkli/jgit
 /**
  * Write the entry records from memory to disk.
  *
  * <p>The cache must be locked first by calling {@link #lock()} and receiving true as the return
  * value. Applications are encouraged to lock the index, then invoke {@link #read()} to ensure the
  * in-memory data is current, prior to updating the in-memory entries.
  *
  * <p>Once written the lock is closed and must be either committed with {@link #commit()} or
  * rolled back with {@link #unlock()}.
  *
  * @throws IOException the output file could not be created. The caller no longer holds the lock.
  */
 public void write() throws IOException {
   final LockFile tmp = myLock;
   requireLocked(tmp);
   try {
     writeTo(new SafeBufferedOutputStream(tmp.getOutputStream()));
   } catch (IOException err) {
     tmp.unlock();
     throw err;
   } catch (RuntimeException err) {
     tmp.unlock();
     throw err;
   } catch (Error err) {
     tmp.unlock();
     throw err;
   }
 }
예제 #6
0
  /**
   * Save the configuration as a Git text style configuration file.
   *
   * <p><b>Warning:</b> Although this method uses the traditional Git file locking approach to
   * protect against concurrent writes of the configuration file, it does not ensure that the file
   * has not been modified since the last read, which means updates performed by other objects
   * accessing the same backing file may be lost.
   *
   * @throws IOException the file could not be written.
   */
  public void save() throws IOException {
    final byte[] out;
    final String text = toText();
    if (utf8Bom) {
      final ByteArrayOutputStream bos = new ByteArrayOutputStream();
      bos.write(0xEF);
      bos.write(0xBB);
      bos.write(0xBF);
      bos.write(text.getBytes(RawParseUtils.UTF8_CHARSET.name()));
      out = bos.toByteArray();
    } else {
      out = Constants.encode(text);
    }

    final LockFile lf = new LockFile(getFile(), fs);
    if (!lf.lock()) throw new LockFailedException(getFile());
    try {
      lf.setNeedSnapshot(true);
      lf.write(out);
      if (!lf.commit())
        throw new IOException(MessageFormat.format(JGitText.get().cannotCommitWriteTo, getFile()));
    } finally {
      lf.unlock();
    }
    snapshot = lf.getCommitSnapshot();
    hash = hash(out);
    // notify the listeners
    fireConfigChangedEvent();
  }