Пример #1
0
  /**
   * 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());
  }
Пример #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());
    }
  }
Пример #3
0
  /**
   * 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);
    }
  }
Пример #4
0
  /**
   * Executes the export operation using the parameters that have been specified.
   *
   * @return a FeatureCollection with the specified features
   */
  @Override
  protected SimpleFeatureStore _call() {
    final ObjectDatabase database = objectDatabase();
    if (filterFeatureTypeId != null) {
      RevObject filterType = database.getIfPresent(filterFeatureTypeId);
      checkArgument(
          filterType instanceof RevFeatureType, "Provided filter feature type is does not exist");
    }

    final SimpleFeatureStore targetStore = getTargetStore();

    final String refspec = resolveRefSpec();
    final String treePath = refspec.substring(refspec.indexOf(':') + 1);
    final RevTree rootTree = resolveRootTree(refspec);
    final NodeRef typeTreeRef = resolTypeTreeRef(refspec, treePath, rootTree);

    final ObjectId defaultMetadataId = typeTreeRef.getMetadataId();

    final RevTree typeTree = database.getTree(typeTreeRef.getObjectId());

    final ProgressListener progressListener = getProgressListener();

    progressListener.started();
    progressListener.setDescription(
        "Exporting from " + path + " to " + targetStore.getName().getLocalPart() + "... ");

    final Iterator<SimpleFeature> filtered;
    {
      final Iterator<SimpleFeature> plainFeatures =
          getFeatures(typeTree, database, defaultMetadataId, progressListener);

      Iterator<SimpleFeature> adaptedFeatures = adaptToArguments(plainFeatures, defaultMetadataId);

      Iterator<Optional<Feature>> transformed =
          Iterators.transform(adaptedFeatures, ExportOp.this.function);

      Iterator<SimpleFeature> result =
          Iterators.filter(
              Iterators.transform(
                  transformed,
                  new Function<Optional<Feature>, SimpleFeature>() {
                    @Override
                    public SimpleFeature apply(Optional<Feature> input) {
                      return (SimpleFeature) input.orNull();
                    }
                  }),
              Predicates.notNull());

      // check the resulting schema has something to contribute
      PeekingIterator<SimpleFeature> peekingIt = Iterators.peekingIterator(result);
      if (peekingIt.hasNext()) {
        Function<AttributeDescriptor, String> toString =
            new Function<AttributeDescriptor, String>() {
              @Override
              public String apply(AttributeDescriptor input) {
                return input.getLocalName();
              }
            };
        SimpleFeature peek = peekingIt.peek();
        Set<String> sourceAtts =
            new HashSet<String>(
                Lists.transform(peek.getFeatureType().getAttributeDescriptors(), toString));
        Set<String> targetAtts =
            new HashSet<String>(
                Lists.transform(targetStore.getSchema().getAttributeDescriptors(), toString));
        if (Sets.intersection(sourceAtts, targetAtts).isEmpty()) {
          throw new GeoToolsOpException(
              StatusCode.UNABLE_TO_ADD,
              "No common attributes between source and target feature types");
        }
      }

      filtered = peekingIt;
    }
    FeatureCollection<SimpleFeatureType, SimpleFeature> asFeatureCollection =
        new BaseFeatureCollection<SimpleFeatureType, SimpleFeature>() {

          @Override
          public FeatureIterator<SimpleFeature> features() {

            return new DelegateFeatureIterator<SimpleFeature>(filtered);
          }
        };

    // add the feature collection to the feature store
    final Transaction transaction;
    if (transactional) {
      transaction = new DefaultTransaction("create");
    } else {
      transaction = Transaction.AUTO_COMMIT;
    }
    try {
      targetStore.setTransaction(transaction);
      try {
        targetStore.addFeatures(asFeatureCollection);
        transaction.commit();
      } catch (final Exception e) {
        if (transactional) {
          transaction.rollback();
        }
        Throwables.propagateIfInstanceOf(e, GeoToolsOpException.class);
        throw new GeoToolsOpException(e, StatusCode.UNABLE_TO_ADD);
      } finally {
        transaction.close();
      }
    } catch (IOException e) {
      throw new GeoToolsOpException(e, StatusCode.UNABLE_TO_ADD);
    }

    progressListener.complete();

    return targetStore;
  }
Пример #5
0
  /**
   * Retrieve objects from the remote repository, and update have/want lists accordingly.
   * Specifically, any retrieved commits are removed from the want list and added to the have list,
   * and any parents of those commits are removed from the have list (it only represents the most
   * recent common commits.) Retrieved objects are added to the local repository, and the want/have
   * lists are updated in-place.
   *
   * @param want a list of ObjectIds that need to be fetched
   * @param have a list of ObjectIds that are in common with the remote repository
   * @param progress
   */
  private void fetchMoreData(
      final List<ObjectId> want, final Set<ObjectId> have, final ProgressListener progress) {
    final JsonObject message = createFetchMessage(want, have);
    final URL resourceURL;
    try {
      resourceURL = new URL(repositoryURL.toString() + "/repo/batchobjects");
    } catch (MalformedURLException e) {
      throw Throwables.propagate(e);
    }

    final HttpURLConnection connection;
    try {
      final Gson gson = new Gson();
      OutputStream out;
      final Writer writer;
      connection = (HttpURLConnection) resourceURL.openConnection();
      connection.setDoOutput(true);
      connection.setDoInput(true);
      connection.addRequestProperty("Accept-Encoding", "gzip");
      out = connection.getOutputStream();
      writer = new OutputStreamWriter(out);
      gson.toJson(message, writer);
      writer.flush();
      out.flush();
    } catch (IOException e) {
      throw Throwables.propagate(e);
    }

    final HttpUtils.ReportingInputStream in = HttpUtils.getResponseStream(connection);

    BinaryPackedObjects unpacker = new BinaryPackedObjects(localRepository.objectDatabase());
    BinaryPackedObjects.Callback callback =
        new BinaryPackedObjects.Callback() {
          @Override
          public void callback(Supplier<RevObject> supplier) {
            RevObject object = supplier.get();
            progress.setProgress(progress.getProgress() + 1);
            if (object instanceof RevCommit) {
              RevCommit commit = (RevCommit) object;
              want.remove(commit.getId());
              have.removeAll(commit.getParentIds());
              have.add(commit.getId());
            } else if (object instanceof RevTag) {
              RevTag tag = (RevTag) object;
              want.remove(tag.getId());
              have.remove(tag.getCommitId());
              have.add(tag.getId());
            }
          }
        };

    Stopwatch sw = Stopwatch.createStarted();
    IngestResults ingestResults = unpacker.ingest(in, callback);
    sw.stop();

    String msg =
        String.format(
            "Processed %,d objects. Inserted: %,d. Existing: %,d. Time: %s. Compressed size: %,d bytes. Uncompressed size: %,d bytes.",
            ingestResults.total(),
            ingestResults.getInserted(),
            ingestResults.getExisting(),
            sw,
            in.compressedSize(),
            in.unCompressedSize());
    LOGGER.info(msg);
    progress.setDescription(msg);
  }