private void deleteCommand(final RemoteRefUpdate u) {
    final Ref r = newRefs.remove(u.getRemoteName());
    if (r == null) {
      // Already gone.
      //
      u.setStatus(Status.OK);
      return;
    }

    if (r.getStorage().isPacked()) packedRefUpdates.add(u);

    if (r.getStorage().isLoose()) {
      try {
        dest.deleteRef(u.getRemoteName());
        u.setStatus(Status.OK);
      } catch (IOException e) {
        u.setStatus(Status.REJECTED_OTHER_REASON);
        u.setMessage(e.getMessage());
      }
    }

    try {
      dest.deleteRefLog(u.getRemoteName());
    } catch (IOException e) {
      u.setStatus(Status.REJECTED_OTHER_REASON);
      u.setMessage(e.getMessage());
    }
  }
Beispiel #2
0
    private Map<String, Ref> readAdvertisedImpl(final BufferedReader br)
        throws IOException, PackProtocolException {
      final TreeMap<String, Ref> avail = new TreeMap<String, Ref>();
      for (; ; ) {
        String line = br.readLine();
        if (line == null) break;

        final int tab = line.indexOf('\t');
        if (tab < 0) throw invalidAdvertisement(line);

        String name;
        final ObjectId id;

        name = line.substring(tab + 1);
        id = ObjectId.fromString(line.substring(0, tab));
        if (name.endsWith("^{}")) {
          name = name.substring(0, name.length() - 3);
          final Ref prior = avail.get(name);
          if (prior == null) throw outOfOrderAdvertisement(name);

          if (prior.getPeeledObjectId() != null) throw duplicateAdvertisement(name + "^{}");

          avail.put(name, new Ref(Ref.Storage.NETWORK, name, prior.getObjectId(), id, true));
        } else {
          final Ref prior = avail.put(name, new Ref(Ref.Storage.NETWORK, name, id));
          if (prior != null) throw duplicateAdvertisement(name);
        }
      }
      return avail;
    }
  private boolean sendWants(final Collection<Ref> want) throws IOException {
    boolean first = true;
    for (final Ref r : want) {
      try {
        if (walk.parseAny(r.getObjectId()).has(REACHABLE)) {
          // We already have this object. Asking for it is
          // not a very good idea.
          //
          continue;
        }
      } catch (IOException err) {
        // Its OK, we don't have it, but we want to fix that
        // by fetching the object from the other side.
      }

      final StringBuilder line = new StringBuilder(46);
      line.append("want ");
      line.append(r.getObjectId().name());
      if (first) {
        line.append(enableCapabilities());
        first = false;
      }
      line.append('\n');
      pckOut.writeString(line.toString());
    }
    pckOut.end();
    outNeedsEnd = false;
    return !first;
  }
 private void deleteAllRefs() throws Exception {
   final RevWalk rw = new RevWalk(db);
   for (final Ref r : db.getAllRefs().values()) {
     if (Constants.HEAD.equals(r.getName())) continue;
     final RefUpdate u = db.updateRef(r.getName());
     u.setForceUpdate(true);
     u.delete(rw);
   }
 }
Beispiel #5
0
    private void verifyPrerequisites() throws TransportException {
      if (prereqs.isEmpty()) return;

      final RevWalk rw = new RevWalk(local);
      final RevFlag PREREQ = rw.newFlag("PREREQ");
      final RevFlag SEEN = rw.newFlag("SEEN");

      final List<ObjectId> missing = new ArrayList<ObjectId>();
      final List<RevObject> commits = new ArrayList<RevObject>();
      for (final ObjectId p : prereqs) {
        try {
          final RevCommit c = rw.parseCommit(p);
          if (!c.has(PREREQ)) {
            c.add(PREREQ);
            commits.add(c);
          }
        } catch (MissingObjectException notFound) {
          missing.add(p);
        } catch (IOException err) {
          throw new TransportException(uri, "Cannot read commit " + p.name(), err);
        }
      }
      if (!missing.isEmpty()) throw new MissingBundlePrerequisiteException(uri, missing);

      for (final Ref r : local.getAllRefs().values()) {
        try {
          rw.markStart(rw.parseCommit(r.getObjectId()));
        } catch (IOException readError) {
          // If we cannot read the value of the ref skip it.
        }
      }

      int remaining = commits.size();
      try {
        RevCommit c;
        while ((c = rw.next()) != null) {
          if (c.has(PREREQ)) {
            c.add(SEEN);
            if (--remaining == 0) break;
          }
        }
      } catch (IOException err) {
        throw new TransportException(uri, "Cannot read object", err);
      }

      if (remaining > 0) {
        for (final RevObject o : commits) {
          if (!o.has(SEEN)) missing.add(o);
        }
        throw new MissingBundlePrerequisiteException(uri, missing);
      }
    }
 private int maxTimeWanted(final Collection<Ref> wants) {
   int maxTime = 0;
   for (final Ref r : wants) {
     try {
       final RevObject obj = walk.parseAny(r.getObjectId());
       if (obj instanceof RevCommit) {
         final int cTime = ((RevCommit) obj).getCommitTime();
         if (maxTime < cTime) maxTime = cTime;
       }
     } catch (IOException error) {
       // We don't have it, but we want to fetch (thus fixing error).
     }
   }
   return maxTime;
 }
Beispiel #7
0
 private Ref guessHEAD(final FetchResult result) {
   final Ref idHEAD = result.getAdvertisedRef(Constants.HEAD);
   final List<Ref> availableRefs = new ArrayList<Ref>();
   Ref head = null;
   for (final Ref r : result.getAdvertisedRefs()) {
     final String n = r.getName();
     if (!n.startsWith(Constants.R_HEADS)) continue;
     availableRefs.add(r);
     if (idHEAD == null || head != null) continue;
     if (r.getObjectId().equals(idHEAD.getObjectId())) head = r;
   }
   Collections.sort(availableRefs, RefComparator.INSTANCE);
   if (idHEAD != null && head == null) head = idHEAD;
   return head;
 }
Beispiel #8
0
  private void doCheckout(final Ref branch) throws IOException {
    if (branch == null) throw die("cannot checkout; no HEAD advertised by remote");
    if (!Constants.HEAD.equals(branch.getName())) db.writeSymref(Constants.HEAD, branch.getName());

    final Commit commit = db.mapCommit(branch.getObjectId());
    final RefUpdate u = db.updateRef(Constants.HEAD);
    u.setNewObjectId(commit.getCommitId());
    u.forceUpdate();

    final GitIndex index = new GitIndex(db);
    final Tree tree = commit.getTree();
    final WorkDirCheckout co;

    co = new WorkDirCheckout(db, db.getWorkDir(), index, tree);
    co.checkout();
    index.write();
  }
  private void markReachable(final Set<ObjectId> have, final int maxTime) throws IOException {
    for (final Ref r : local.getAllRefs().values()) {
      try {
        final RevCommit o = walk.parseCommit(r.getObjectId());
        o.add(REACHABLE);
        reachableCommits.add(o);
      } catch (IOException readError) {
        // If we cannot read the value of the ref skip it.
      }
    }

    for (final ObjectId id : have) {
      try {
        final RevCommit o = walk.parseCommit(id);
        o.add(REACHABLE);
        reachableCommits.add(o);
      } catch (IOException readError) {
        // If we cannot read the value of the ref skip it.
      }
    }

    if (maxTime > 0) {
      // Mark reachable commits until we reach maxTime. These may
      // wind up later matching up against things we want and we
      // can avoid asking for something we already happen to have.
      //
      final Date maxWhen = new Date(maxTime * 1000L);
      walk.sort(RevSort.COMMIT_TIME_DESC);
      walk.markStart(reachableCommits);
      walk.setRevFilter(CommitTimeRevFilter.after(maxWhen));
      for (; ; ) {
        final RevCommit c = walk.next();
        if (c == null) break;
        if (c.has(ADVERTISED) && !c.has(COMMON)) {
          // This is actually going to be a common commit, but
          // our peer doesn't know that fact yet.
          //
          c.add(COMMON);
          c.carry(COMMON);
          reachableCommits.add(c);
        }
      }
    }
  }
Beispiel #10
0
  /**
   * Convert push remote refs update specification from {@link RefSpec} form to {@link
   * RemoteRefUpdate}. Conversion expands wildcards by matching source part to local refs.
   * expectedOldObjectId in RemoteRefUpdate is always set as null. Tracking branch is configured if
   * RefSpec destination matches source of any fetch ref spec for this transport remote
   * configuration.
   *
   * @param db local database.
   * @param specs collection of RefSpec to convert.
   * @param fetchSpecs fetch specifications used for finding localtracking refs. May be null or
   *     empty collection.
   * @return collection of set up {@link RemoteRefUpdate}.
   * @throws IOException when problem occurred during conversion or specification set up: most
   *     probably, missing objects or refs.
   */
  public static Collection<RemoteRefUpdate> findRemoteRefUpdatesFor(
      final Repository db, final Collection<RefSpec> specs, Collection<RefSpec> fetchSpecs)
      throws IOException {
    if (fetchSpecs == null) fetchSpecs = Collections.emptyList();
    final List<RemoteRefUpdate> result = new LinkedList<RemoteRefUpdate>();
    final Collection<RefSpec> procRefs = expandPushWildcardsFor(db, specs);

    for (final RefSpec spec : procRefs) {
      String srcSpec = spec.getSource();
      final Ref srcRef = db.getRef(srcSpec);
      if (srcRef != null) srcSpec = srcRef.getName();

      String destSpec = spec.getDestination();
      if (destSpec == null) {
        // No destination (no-colon in ref-spec), DWIMery assumes src
        //
        destSpec = srcSpec;
      }

      if (srcRef != null && !destSpec.startsWith(Constants.R_REFS)) {
        // Assume the same kind of ref at the destination, e.g.
        // "refs/heads/foo:master", DWIMery assumes master is also
        // under "refs/heads/".
        //
        final String n = srcRef.getName();
        final int kindEnd = n.indexOf('/', Constants.R_REFS.length());
        destSpec = n.substring(0, kindEnd + 1) + destSpec;
      }

      final boolean forceUpdate = spec.isForceUpdate();
      final String localName = findTrackingRefName(destSpec, fetchSpecs);
      final RemoteRefUpdate rru =
          new RemoteRefUpdate(db, srcSpec, destSpec, forceUpdate, localName, null);
      result.add(rru);
    }
    return result;
  }
  private void sendpack(final List<RemoteRefUpdate> updates, final ProgressMonitor monitor)
      throws TransportException {
    String pathPack = null;
    String pathIdx = null;

    try {
      final PackWriter pw = new PackWriter(local, monitor);
      final List<ObjectId> need = new ArrayList<ObjectId>();
      final List<ObjectId> have = new ArrayList<ObjectId>();
      for (final RemoteRefUpdate r : updates) need.add(r.getNewObjectId());
      for (final Ref r : getRefs()) {
        have.add(r.getObjectId());
        if (r.getPeeledObjectId() != null) have.add(r.getPeeledObjectId());
      }
      pw.preparePack(need, have, false, true);

      // We don't have to continue further if the pack will
      // be an empty pack, as the remote has all objects it
      // needs to complete this change.
      //
      if (pw.getObjectsNumber() == 0) return;

      packNames = new LinkedHashMap<String, String>();
      for (final String n : dest.getPackNames()) packNames.put(n, n);

      final String base = "pack-" + pw.computeName().name();
      final String packName = base + ".pack";
      pathPack = "pack/" + packName;
      pathIdx = "pack/" + base + ".idx";

      if (packNames.remove(packName) != null) {
        // The remote already contains this pack. We should
        // remove the index before overwriting to prevent bad
        // offsets from appearing to clients.
        //
        dest.writeInfoPacks(packNames.keySet());
        dest.deleteFile(pathIdx);
      }

      // Write the pack file, then the index, as readers look the
      // other direction (index, then pack file).
      //
      final String wt = "Put " + base.substring(0, 12);
      OutputStream os = dest.writeFile(pathPack, monitor, wt + "..pack");
      try {
        pw.writePack(os);
      } finally {
        os.close();
      }

      os = dest.writeFile(pathIdx, monitor, wt + "..idx");
      try {
        pw.writeIndex(os);
      } finally {
        os.close();
      }

      // Record the pack at the start of the pack info list. This
      // way clients are likely to consult the newest pack first,
      // and discover the most recent objects there.
      //
      final ArrayList<String> infoPacks = new ArrayList<String>();
      infoPacks.add(packName);
      infoPacks.addAll(packNames.keySet());
      dest.writeInfoPacks(infoPacks);

    } catch (IOException err) {
      safeDelete(pathIdx);
      safeDelete(pathPack);

      throw new TransportException(uri, "cannot store objects", err);
    }
  }
 private void markRefsAdvertised() {
   for (final Ref r : getRefs()) {
     markAdvertised(r.getObjectId());
     if (r.getPeeledObjectId() != null) markAdvertised(r.getPeeledObjectId());
   }
 }