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()); } }
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); } }
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; }
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; }
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); } } } }
/** * 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()); } }