예제 #1
0
 private List<ReceiveCommand> filterCommands(final Result want) {
   final List<ReceiveCommand> r = new ArrayList<ReceiveCommand>(commands.size());
   for (final ReceiveCommand cmd : commands) {
     if (cmd.getResult() == want) r.add(cmd);
   }
   return r;
 }
예제 #2
0
  private void execute(final ReceiveCommand cmd) {
    try {
      final RefUpdate ru = db.updateRef(cmd.getRefName());
      ru.setRefLogIdent(getRefLogIdent());
      switch (cmd.getType()) {
        case DELETE:
          if (!ObjectId.zeroId().equals(cmd.getOldId())) {
            // We can only do a CAS style delete if the client
            // didn't bork its delete request by sending the
            // wrong zero id rather than the advertised one.
            //
            ru.setExpectedOldObjectId(cmd.getOldId());
          }
          ru.setForceUpdate(true);
          status(cmd, ru.delete(walk));
          break;

        case CREATE:
        case UPDATE:
        case UPDATE_NONFASTFORWARD:
          ru.setForceUpdate(isAllowNonFastForwards());
          ru.setExpectedOldObjectId(cmd.getOldId());
          ru.setNewObjectId(cmd.getNewId());
          ru.setRefLogMessage("push", true);
          status(cmd, ru.update(walk));
          break;
      }
    } catch (IOException err) {
      cmd.setResult(
          Result.REJECTED_OTHER_REASON,
          MessageFormat.format(JGitText.get().lockError, err.getMessage()));
    }
  }
예제 #3
0
  private void status(final ReceiveCommand cmd, final RefUpdate.Result result) {
    switch (result) {
      case NOT_ATTEMPTED:
        cmd.setResult(Result.NOT_ATTEMPTED);
        break;

      case LOCK_FAILURE:
      case IO_FAILURE:
        cmd.setResult(Result.LOCK_FAILURE);
        break;

      case NO_CHANGE:
      case NEW:
      case FORCED:
      case FAST_FORWARD:
        cmd.setResult(Result.OK);
        break;

      case REJECTED:
        cmd.setResult(Result.REJECTED_NONFASTFORWARD);
        break;

      case REJECTED_CURRENT_BRANCH:
        cmd.setResult(Result.REJECTED_CURRENT_BRANCH);
        break;

      default:
        cmd.setResult(Result.REJECTED_OTHER_REASON, result.name());
        break;
    }
  }
예제 #4
0
  private void recvCommands() throws IOException {
    for (; ; ) {
      String line;
      try {
        line = pckIn.readStringRaw();
      } catch (EOFException eof) {
        if (commands.isEmpty()) return;
        throw eof;
      }
      if (line == PacketLineIn.END) break;

      if (commands.isEmpty()) {
        final int nul = line.indexOf('\0');
        if (nul >= 0) {
          for (String c : line.substring(nul + 1).split(" ")) enabledCapablities.add(c);
          line = line.substring(0, nul);
        }
      }

      if (line.length() < 83) {
        final String m = JGitText.get().errorInvalidProtocolWantedOldNewRef;
        sendError(m);
        throw new PackProtocolException(m);
      }

      final ObjectId oldId = ObjectId.fromString(line.substring(0, 40));
      final ObjectId newId = ObjectId.fromString(line.substring(41, 81));
      final String name = line.substring(82);
      final ReceiveCommand cmd = new ReceiveCommand(oldId, newId, name);
      if (name.equals(Constants.HEAD)) {
        cmd.setResult(Result.REJECTED_CURRENT_BRANCH);
      } else {
        cmd.setRef(refs.get(cmd.getRefName()));
      }
      commands.add(cmd);
    }
  }
예제 #5
0
 @Override
 public void setResult(ReceiveCommand.Result status, String msg) {
   result = decode(status);
   super.setResult(status, msg);
 }
예제 #6
0
 @Override
 public void setResult(RefUpdate.Result status) {
   result = status;
   super.setResult(status);
 }
예제 #7
0
  private void validateCommands() {
    for (final ReceiveCommand cmd : commands) {
      final Ref ref = cmd.getRef();
      if (cmd.getResult() != Result.NOT_ATTEMPTED) continue;

      if (cmd.getType() == ReceiveCommand.Type.DELETE && !isAllowDeletes()) {
        // Deletes are not supported on this repository.
        //
        cmd.setResult(Result.REJECTED_NODELETE);
        continue;
      }

      if (cmd.getType() == ReceiveCommand.Type.CREATE) {
        if (!isAllowCreates()) {
          cmd.setResult(Result.REJECTED_NOCREATE);
          continue;
        }

        if (ref != null && !isAllowNonFastForwards()) {
          // Creation over an existing ref is certainly not going
          // to be a fast-forward update. We can reject it early.
          //
          cmd.setResult(Result.REJECTED_NONFASTFORWARD);
          continue;
        }

        if (ref != null) {
          // A well behaved client shouldn't have sent us a
          // create command for a ref we advertised to it.
          //
          cmd.setResult(
              Result.REJECTED_OTHER_REASON,
              MessageFormat.format(JGitText.get().refAlreadyExists, ref));
          continue;
        }
      }

      if (cmd.getType() == ReceiveCommand.Type.DELETE
          && ref != null
          && !ObjectId.zeroId().equals(cmd.getOldId())
          && !ref.getObjectId().equals(cmd.getOldId())) {
        // Delete commands can be sent with the old id matching our
        // advertised value, *OR* with the old id being 0{40}. Any
        // other requested old id is invalid.
        //
        cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().invalidOldIdSent);
        continue;
      }

      if (cmd.getType() == ReceiveCommand.Type.UPDATE) {
        if (ref == null) {
          // The ref must have been advertised in order to be updated.
          //
          cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().noSuchRef);
          continue;
        }

        if (!ref.getObjectId().equals(cmd.getOldId())) {
          // A properly functioning client will send the same
          // object id we advertised.
          //
          cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().invalidOldIdSent);
          continue;
        }

        // Is this possibly a non-fast-forward style update?
        //
        RevObject oldObj, newObj;
        try {
          oldObj = walk.parseAny(cmd.getOldId());
        } catch (IOException e) {
          cmd.setResult(Result.REJECTED_MISSING_OBJECT, cmd.getOldId().name());
          continue;
        }

        try {
          newObj = walk.parseAny(cmd.getNewId());
        } catch (IOException e) {
          cmd.setResult(Result.REJECTED_MISSING_OBJECT, cmd.getNewId().name());
          continue;
        }

        if (oldObj instanceof RevCommit && newObj instanceof RevCommit) {
          try {
            if (!walk.isMergedInto((RevCommit) oldObj, (RevCommit) newObj)) {
              cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
            }
          } catch (MissingObjectException e) {
            cmd.setResult(Result.REJECTED_MISSING_OBJECT, e.getMessage());
          } catch (IOException e) {
            cmd.setResult(Result.REJECTED_OTHER_REASON);
          }
        } else {
          cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
        }
      }

      if (!cmd.getRefName().startsWith(Constants.R_REFS)
          || !Repository.isValidRefName(cmd.getRefName())) {
        cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().funnyRefname);
      }
    }
  }
예제 #8
0
  private void checkConnectivity() throws IOException {
    ObjectIdSubclassMap<ObjectId> baseObjects = null;
    ObjectIdSubclassMap<ObjectId> providedObjects = null;

    if (checkReferencedIsReachable) {
      baseObjects = parser.getBaseObjectIds();
      providedObjects = parser.getNewObjectIds();
    }
    parser = null;

    final ObjectWalk ow = new ObjectWalk(db);
    ow.setRetainBody(false);
    if (checkReferencedIsReachable) {
      ow.sort(RevSort.TOPO);
      if (!baseObjects.isEmpty()) ow.sort(RevSort.BOUNDARY, true);
    }

    for (final ReceiveCommand cmd : commands) {
      if (cmd.getResult() != Result.NOT_ATTEMPTED) continue;
      if (cmd.getType() == ReceiveCommand.Type.DELETE) continue;
      ow.markStart(ow.parseAny(cmd.getNewId()));
    }
    for (final ObjectId have : advertisedHaves) {
      RevObject o = ow.parseAny(have);
      ow.markUninteresting(o);

      if (checkReferencedIsReachable && !baseObjects.isEmpty()) {
        o = ow.peel(o);
        if (o instanceof RevCommit) o = ((RevCommit) o).getTree();
        if (o instanceof RevTree) ow.markUninteresting(o);
      }
    }

    RevCommit c;
    while ((c = ow.next()) != null) {
      if (checkReferencedIsReachable //
          && !c.has(RevFlag.UNINTERESTING) //
          && !providedObjects.contains(c))
        throw new MissingObjectException(c, Constants.TYPE_COMMIT);
    }

    RevObject o;
    while ((o = ow.nextObject()) != null) {
      if (o.has(RevFlag.UNINTERESTING)) continue;

      if (checkReferencedIsReachable) {
        if (providedObjects.contains(o)) continue;
        else throw new MissingObjectException(o, o.getType());
      }

      if (o instanceof RevBlob && !db.hasObject(o))
        throw new MissingObjectException(o, Constants.TYPE_BLOB);
    }

    if (checkReferencedIsReachable) {
      for (ObjectId id : baseObjects) {
        o = ow.parseAny(id);
        if (!o.has(RevFlag.UNINTERESTING)) throw new MissingObjectException(o, o.getType());
      }
    }
  }
예제 #9
0
 private boolean needPack() {
   for (final ReceiveCommand cmd : commands) {
     if (cmd.getType() != ReceiveCommand.Type.DELETE) return true;
   }
   return false;
 }
예제 #10
0
  private void sendStatusReport(final boolean forClient, final Reporter out) throws IOException {
    if (unpackError != null) {
      out.sendString("unpack error " + unpackError.getMessage());
      if (forClient) {
        for (final ReceiveCommand cmd : commands) {
          out.sendString("ng " + cmd.getRefName() + " n/a (unpacker error)");
        }
      }
      return;
    }

    if (forClient) out.sendString("unpack ok");
    for (final ReceiveCommand cmd : commands) {
      if (cmd.getResult() == Result.OK) {
        if (forClient) out.sendString("ok " + cmd.getRefName());
        continue;
      }

      final StringBuilder r = new StringBuilder();
      r.append("ng ");
      r.append(cmd.getRefName());
      r.append(" ");

      switch (cmd.getResult()) {
        case NOT_ATTEMPTED:
          r.append("server bug; ref not processed");
          break;

        case REJECTED_NOCREATE:
          r.append("creation prohibited");
          break;

        case REJECTED_NODELETE:
          r.append("deletion prohibited");
          break;

        case REJECTED_NONFASTFORWARD:
          r.append("non-fast forward");
          break;

        case REJECTED_CURRENT_BRANCH:
          r.append("branch is currently checked out");
          break;

        case REJECTED_MISSING_OBJECT:
          if (cmd.getMessage() == null) r.append("missing object(s)");
          else if (cmd.getMessage().length() == Constants.OBJECT_ID_STRING_LENGTH)
            r.append("object " + cmd.getMessage() + " missing");
          else r.append(cmd.getMessage());
          break;

        case REJECTED_OTHER_REASON:
          if (cmd.getMessage() == null) r.append("unspecified reason");
          else r.append(cmd.getMessage());
          break;

        case LOCK_FAILURE:
          r.append("failed to lock");
          break;

        case OK:
          // We shouldn't have reached this case (see 'ok' case above).
          continue;
      }
      out.sendString(r.toString());
    }
  }