/**
   * Push all new objects from the specified {@link Ref} to the remote.
   *
   * @param ref the local ref that points to new commit data
   * @param refspec the remote branch to push to
   */
  @Override
  public void pushNewData(Ref ref, String refspec, ProgressListener progress)
      throws SynchronizationException {
    Optional<Ref> remoteRef = HttpUtils.getRemoteRef(repositoryURL, refspec);
    checkPush(ref, remoteRef);
    beginPush();

    progress.setDescription("Uploading objects to " + refspec);
    progress.setProgress(0);

    CommitTraverser traverser = getPushTraverser(remoteRef);

    traverser.traverse(ref.getObjectId());

    List<ObjectId> toSend = new LinkedList<ObjectId>(traverser.commits);
    Collections.reverse(toSend);
    Set<ObjectId> have = new HashSet<ObjectId>(traverser.have);

    Deduplicator deduplicator = deduplicationService.createDeduplicator();
    try {
      sendPackedObjects(toSend, have, deduplicator, progress);
    } finally {
      deduplicator.release();
    }

    ObjectId originalRemoteRefValue = ObjectId.NULL;
    if (remoteRef.isPresent()) {
      originalRemoteRefValue = remoteRef.get().getObjectId();
    }

    String nameToSet =
        remoteRef.isPresent() ? remoteRef.get().getName() : Ref.HEADS_PREFIX + refspec;

    endPush(nameToSet, ref.getObjectId(), originalRemoteRefValue.toString());
  }
Esempio n. 2
0
  /**
   * Stages the object addressed by {@code pathFilter}, or all unstaged objects if {@code pathFilter
   * == null} to be added, if it is/they are marked as an unstaged change. Does nothing otherwise.
   *
   * <p>To stage changes not yet staged, a diff tree walk is performed using the current staged
   * {@link RevTree} as the old object and the current unstaged {@link RevTree} as the new object.
   * Then all the differences are traversed and the staged tree is updated with the changes reported
   * by the diff walk (neat).
   *
   * @param progress the progress listener for this process
   * @param pathFilter the filter to use
   */
  public void stage(final ProgressListener progress, final @Nullable String pathFilter) {

    // short cut for the case where the index is empty and we're staging all changes in the
    // working tree, so it's just a matter of updating the index ref to working tree RevTree id
    if (null == pathFilter
        && !index().getStaged(null).hasNext()
        && !updateOnly
        && index().countConflicted(null) == 0) {
      progress.started();
      Optional<ObjectId> workHead = command(RevParse.class).setRefSpec(Ref.WORK_HEAD).call();
      if (workHead.isPresent()) {
        command(UpdateRef.class).setName(Ref.STAGE_HEAD).setNewValue(workHead.get()).call();
      }
      progress.setProgress(100f);
      progress.complete();
      return;
    }

    final long numChanges = workingTree().countUnstaged(pathFilter).count();

    Iterator<DiffEntry> unstaged = workingTree().getUnstaged(pathFilter);

    if (updateOnly) {
      unstaged =
          Iterators.filter(
              unstaged,
              new Predicate<DiffEntry>() {
                @Override
                public boolean apply(@Nullable DiffEntry input) {
                  // HACK: avoid reporting changed trees
                  if (input.isChange() && input.getOldObject().getType().equals(TYPE.TREE)) {
                    return false;
                  }
                  return input.getOldObject() != null;
                }
              });
    }

    index().stage(progress, unstaged, numChanges);

    List<Conflict> conflicts = index().getConflicted(pathFilter);
    ConflictsDatabase conflictsDatabase = conflictsDatabase();
    for (Conflict conflict : conflicts) {
      // if we are staging unmerged files, the conflict should get solved. However, if the
      // working index object is the same as the staging area one (for instance, after running
      // checkout --ours), it will not be reported by the getUnstaged method. We solve that
      // here.
      conflictsDatabase.removeConflict(null, conflict.getPath());
    }
  }
  /**
   * Fetch all new objects from the specified {@link Ref} from the remote.
   *
   * @param ref the remote ref that points to new commit data
   * @param fetchLimit the maximum depth to fetch
   */
  @Override
  public void fetchNewData(Ref ref, Optional<Integer> fetchLimit, ProgressListener progress) {

    CommitTraverser traverser = getFetchTraverser(fetchLimit);

    try {
      progress.setDescription("Fetching objects from " + ref.getName());
      traverser.traverse(ref.getObjectId());
      List<ObjectId> want = new LinkedList<ObjectId>();
      want.addAll(traverser.commits);
      Collections.reverse(want);
      Set<ObjectId> have = new HashSet<ObjectId>();
      have.addAll(traverser.have);
      while (!want.isEmpty()) {
        progress.setProgress(0);
        fetchMoreData(want, have, progress);
      }
    } catch (Exception e) {
      Throwables.propagate(e);
    }
  }