예제 #1
0
 /**
  * Updates the file in the working tree with content and mode from an entry in the index. The new
  * content is first written to a new temporary file in the same directory as the real file. Then
  * that new file is renamed to the final filename.
  *
  * <p>TODO: this method works directly on File IO, we may need another abstraction (like
  * WorkingTreeIterator). This way we could tell e.g. Eclipse that Files in the workspace got
  * changed
  *
  * @param repo
  * @param f the file to be modified. The parent directory for this file has to exist already
  * @param entry the entry containing new mode and content
  * @param or object reader to use for checkout
  * @throws IOException
  */
 public static void checkoutEntry(
     final Repository repo, File f, DirCacheEntry entry, ObjectReader or) throws IOException {
   ObjectLoader ol = or.open(entry.getObjectId());
   File parentDir = f.getParentFile();
   parentDir.mkdirs();
   File tmpFile = File.createTempFile("._" + f.getName(), null, parentDir); // $NON-NLS-1$
   WorkingTreeOptions opt = repo.getConfig().get(WorkingTreeOptions.KEY);
   FileOutputStream rawChannel = new FileOutputStream(tmpFile);
   OutputStream channel;
   if (opt.getAutoCRLF() == AutoCRLF.TRUE) channel = new AutoCRLFOutputStream(rawChannel);
   else channel = rawChannel;
   try {
     ol.copyTo(channel);
   } finally {
     channel.close();
   }
   FS fs = repo.getFS();
   if (opt.isFileMode() && fs.supportsExecute()) {
     if (FileMode.EXECUTABLE_FILE.equals(entry.getRawMode())) {
       if (!fs.canExecute(tmpFile)) fs.setExecute(tmpFile, true);
     } else {
       if (fs.canExecute(tmpFile)) fs.setExecute(tmpFile, false);
     }
   }
   try {
     FileUtils.rename(tmpFile, f);
   } catch (IOException e) {
     throw new IOException(
         MessageFormat.format(JGitText.get().couldNotWriteFile, tmpFile.getPath(), f.getPath()));
   }
   entry.setLastModified(f.lastModified());
   if (opt.getAutoCRLF() != AutoCRLF.FALSE)
     entry.setLength(f.length()); // AutoCRLF wants on-disk-size
   else entry.setLength((int) ol.getSize());
 }
예제 #2
0
  /**
   * Checks whether this entry differs from a given entry from the {@link DirCache}.
   *
   * <p>File status information is used and if status is same we consider the file identical to the
   * state in the working directory. Native git uses more stat fields than we have accessible in
   * Java.
   *
   * @param entry the entry from the dircache we want to compare against
   * @param forceContentCheck True if the actual file content should be checked if modification time
   *     differs.
   * @return true if content is most likely different.
   */
  public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
    if (entry.isAssumeValid()) return false;

    if (entry.isUpdateNeeded()) return true;

    if (!entry.isSmudged() && (getEntryLength() != entry.getLength())) return true;

    // Determine difference in mode-bits of file and index-entry. In the
    // bitwise presentation of modeDiff we'll have a '1' when the two modes
    // differ at this position.
    int modeDiff = getEntryRawMode() ^ entry.getRawMode();
    // Ignore the executable file bits if checkFilemode tells me to do so.
    // Ignoring is done by setting the bits representing a EXECUTABLE_FILE
    // to '0' in modeDiff
    if (!state.options.isFileMode()) modeDiff &= ~FileMode.EXECUTABLE_FILE.getBits();
    if (modeDiff != 0)
      // Report a modification if the modes still (after potentially
      // ignoring EXECUTABLE_FILE bits) differ
      return true;

    // Git under windows only stores seconds so we round the timestamp
    // Java gives us if it looks like the timestamp in index is seconds
    // only. Otherwise we compare the timestamp at millisecond precision.
    long cacheLastModified = entry.getLastModified();
    long fileLastModified = getEntryLastModified();
    if (cacheLastModified % 1000 == 0)
      fileLastModified = fileLastModified - fileLastModified % 1000;

    if (fileLastModified != cacheLastModified) {
      // The file is dirty by timestamps
      if (forceContentCheck) {
        // But we are told to look at content even though timestamps
        // tell us about modification
        return contentCheck(entry);
      } else {
        // We are told to assume a modification if timestamps differs
        return true;
      }
    } else {
      // The file is clean when you look at timestamps.
      if (entry.isSmudged()) {
        // The file is clean by timestamps but the entry was smudged.
        // Lets do a content check
        return contentCheck(entry);
      } else {
        // The file is clean by timestamps and the entry is not
        // smudged: Can't get any cleaner!
        return false;
      }
    }
  }
예제 #3
0
  void updateSubmoduleSubscriptions(ReviewDb db, Branch.NameKey destBranch)
      throws SubmoduleException {
    if (urlProvider.get() == null) {
      logAndThrowSubmoduleException(
          "Cannot establish canonical web url used "
              + "to access gerrit. It should be provided in gerrit.config file.");
    }
    try (Repository repo = repoManager.openRepository(destBranch.getParentKey());
        RevWalk rw = new RevWalk(repo)) {

      ObjectId id = repo.resolve(destBranch.get());
      RevCommit commit = rw.parseCommit(id);

      Set<SubmoduleSubscription> oldSubscriptions =
          Sets.newHashSet(db.submoduleSubscriptions().bySuperProject(destBranch));

      Set<SubmoduleSubscription> newSubscriptions;
      TreeWalk tw = TreeWalk.forPath(repo, GIT_MODULES, commit.getTree());
      if (tw != null
          && (FileMode.REGULAR_FILE.equals(tw.getRawMode(0))
              || FileMode.EXECUTABLE_FILE.equals(tw.getRawMode(0)))) {
        BlobBasedConfig bbc = new BlobBasedConfig(null, repo, commit, GIT_MODULES);

        String thisServer = new URI(urlProvider.get()).getHost();

        newSubscriptions =
            subSecParserFactory.create(bbc, thisServer, destBranch).parseAllSections();
      } else {
        newSubscriptions = Collections.emptySet();
      }

      Set<SubmoduleSubscription> alreadySubscribeds = new HashSet<>();
      for (SubmoduleSubscription s : newSubscriptions) {
        if (oldSubscriptions.contains(s)) {
          alreadySubscribeds.add(s);
        }
      }

      oldSubscriptions.removeAll(newSubscriptions);
      newSubscriptions.removeAll(alreadySubscribeds);

      if (!oldSubscriptions.isEmpty()) {
        db.submoduleSubscriptions().delete(oldSubscriptions);
      }
      if (!newSubscriptions.isEmpty()) {
        db.submoduleSubscriptions().insert(newSubscriptions);
      }

    } catch (OrmException e) {
      logAndThrowSubmoduleException(
          "Database problem at update of subscriptions table from " + GIT_MODULES + " file.", e);
    } catch (ConfigInvalidException e) {
      logAndThrowSubmoduleException(
          "Problem at update of subscriptions table: " + GIT_MODULES + " config file is invalid.",
          e);
    } catch (IOException e) {
      logAndThrowSubmoduleException(
          "Problem at update of subscriptions table from " + GIT_MODULES + ".", e);
    } catch (URISyntaxException e) {
      logAndThrowSubmoduleException(
          "Incorrect gerrit canonical web url provided in gerrit.config file.", e);
    }
  }