use of org.eclipse.jgit.revwalk.RevObject in project gerrit by GerritCodeReview.
the class ReceiveCommits method isCommit.
private boolean isCommit(ReceiveCommand cmd) {
RevObject obj;
try {
obj = rp.getRevWalk().parseAny(cmd.getNewId());
} catch (IOException err) {
logError("Invalid object " + cmd.getNewId().name() + " for " + cmd.getRefName(), err);
reject(cmd, "invalid object");
return false;
}
if (obj instanceof RevCommit) {
return true;
}
reject(cmd, "not a commit");
return false;
}
use of org.eclipse.jgit.revwalk.RevObject in project gerrit by GerritCodeReview.
the class CreateTag method apply.
@Override
public TagInfo apply(ProjectResource resource, TagInput input) throws RestApiException, IOException, PermissionBackendException {
if (input == null) {
input = new TagInput();
}
if (input.ref != null && !ref.equals(input.ref)) {
throw new BadRequestException("ref must match URL");
}
if (input.revision == null) {
input.revision = Constants.HEAD;
}
ref = RefUtil.normalizeTagRef(ref);
RefControl refControl = resource.getControl().controlForRef(ref);
PermissionBackend.ForRef perm = permissionBackend.user(identifiedUser).project(resource.getNameKey()).ref(ref);
try (Repository repo = repoManager.openRepository(resource.getNameKey())) {
ObjectId revid = RefUtil.parseBaseRevision(repo, resource.getNameKey(), input.revision);
RevWalk rw = RefUtil.verifyConnected(repo, revid);
RevObject object = rw.parseAny(revid);
rw.reset();
boolean isAnnotated = Strings.emptyToNull(input.message) != null;
boolean isSigned = isAnnotated && input.message.contains("-----BEGIN PGP SIGNATURE-----\n");
if (isSigned) {
throw new MethodNotAllowedException("Cannot create signed tag \"" + ref + "\"");
} else if (isAnnotated && !refControl.canPerform(Permission.CREATE_TAG)) {
throw new AuthException("Cannot create annotated tag \"" + ref + "\"");
} else {
perm.check(RefPermission.CREATE);
}
if (repo.getRefDatabase().exactRef(ref) != null) {
throw new ResourceConflictException("tag \"" + ref + "\" already exists");
}
try (Git git = new Git(repo)) {
TagCommand tag = git.tag().setObjectId(object).setName(ref.substring(R_TAGS.length())).setAnnotated(isAnnotated).setSigned(isSigned);
if (isAnnotated) {
tag.setMessage(input.message).setTagger(identifiedUser.get().newCommitterIdent(TimeUtil.nowTs(), TimeZone.getDefault()));
}
Ref result = tag.call();
tagCache.updateFastForward(resource.getNameKey(), ref, ObjectId.zeroId(), result.getObjectId());
referenceUpdated.fire(resource.getNameKey(), ref, ObjectId.zeroId(), result.getObjectId(), identifiedUser.get().getAccount());
try (RevWalk w = new RevWalk(repo)) {
return ListTags.createTagInfo(perm, result, w);
}
}
} catch (InvalidRevisionException e) {
throw new BadRequestException("Invalid base revision");
} catch (GitAPIException e) {
log.error("Cannot create tag \"" + ref + "\"", e);
throw new IOException(e);
}
}
use of org.eclipse.jgit.revwalk.RevObject in project gerrit by GerritCodeReview.
the class CreateBranch method apply.
@Override
public BranchInfo apply(ProjectResource rsrc, BranchInput input) throws BadRequestException, AuthException, ResourceConflictException, IOException {
if (input == null) {
input = new BranchInput();
}
if (input.ref != null && !ref.equals(input.ref)) {
throw new BadRequestException("ref must match URL");
}
if (input.revision == null) {
input.revision = Constants.HEAD;
}
while (ref.startsWith("/")) {
ref = ref.substring(1);
}
ref = RefNames.fullName(ref);
if (!Repository.isValidRefName(ref)) {
throw new BadRequestException("invalid branch name \"" + ref + "\"");
}
if (MagicBranch.isMagicBranch(ref)) {
throw new BadRequestException("not allowed to create branches under \"" + MagicBranch.getMagicRefNamePrefix(ref) + "\"");
}
final Branch.NameKey name = new Branch.NameKey(rsrc.getNameKey(), ref);
final RefControl refControl = rsrc.getControl().controlForRef(name);
try (Repository repo = repoManager.openRepository(rsrc.getNameKey())) {
ObjectId revid = RefUtil.parseBaseRevision(repo, rsrc.getNameKey(), input.revision);
RevWalk rw = RefUtil.verifyConnected(repo, revid);
RevObject object = rw.parseAny(revid);
if (ref.startsWith(Constants.R_HEADS)) {
//
try {
object = rw.parseCommit(object);
} catch (IncorrectObjectTypeException notCommit) {
throw new BadRequestException("\"" + input.revision + "\" not a commit");
}
}
if (!refControl.canCreate(db.get(), repo, object)) {
throw new AuthException("Cannot create \"" + ref + "\"");
}
try {
final RefUpdate u = repo.updateRef(ref);
u.setExpectedOldObjectId(ObjectId.zeroId());
u.setNewObjectId(object.copy());
u.setRefLogIdent(identifiedUser.get().newRefLogIdent());
u.setRefLogMessage("created via REST from " + input.revision, false);
refCreationValidator.validateRefOperation(rsrc.getName(), identifiedUser.get(), u);
final RefUpdate.Result result = u.update(rw);
switch(result) {
case FAST_FORWARD:
case NEW:
case NO_CHANGE:
referenceUpdated.fire(name.getParentKey(), u, ReceiveCommand.Type.CREATE, identifiedUser.get().getAccount());
break;
case LOCK_FAILURE:
if (repo.getRefDatabase().exactRef(ref) != null) {
throw new ResourceConflictException("branch \"" + ref + "\" already exists");
}
String refPrefix = RefUtil.getRefPrefix(ref);
while (!Constants.R_HEADS.equals(refPrefix)) {
if (repo.getRefDatabase().exactRef(refPrefix) != null) {
throw new ResourceConflictException("Cannot create branch \"" + ref + "\" since it conflicts with branch \"" + refPrefix + "\".");
}
refPrefix = RefUtil.getRefPrefix(refPrefix);
}
//$FALL-THROUGH$
case FORCED:
case IO_FAILURE:
case NOT_ATTEMPTED:
case REJECTED:
case REJECTED_CURRENT_BRANCH:
case RENAMED:
default:
{
throw new IOException(result.name());
}
}
BranchInfo info = new BranchInfo();
info.ref = ref;
info.revision = revid.getName();
info.canDelete = permissionBackend.user(identifiedUser).ref(name).testOrFalse(RefPermission.DELETE) ? true : null;
return info;
} catch (IOException err) {
log.error("Cannot create branch \"" + name + "\"", err);
throw err;
}
} catch (RefUtil.InvalidRevisionException e) {
throw new BadRequestException("invalid revision \"" + input.revision + "\"");
}
}
use of org.eclipse.jgit.revwalk.RevObject in project gerrit by GerritCodeReview.
the class ListTags method createTagInfo.
public static TagInfo createTagInfo(PermissionBackend.ForRef perm, Ref ref, RevWalk rw) throws MissingObjectException, IOException {
RevObject object = rw.parseAny(ref.getObjectId());
boolean canDelete = perm.testOrFalse(RefPermission.DELETE);
if (object instanceof RevTag) {
// Annotated or signed tag
RevTag tag = (RevTag) object;
PersonIdent tagger = tag.getTaggerIdent();
return new TagInfo(ref.getName(), tag.getName(), tag.getObject().getName(), tag.getFullMessage().trim(), tagger != null ? CommonConverters.toGitPerson(tag.getTaggerIdent()) : null, canDelete);
}
// Lightweight tag
return new TagInfo(ref.getName(), ref.getObjectId().getName(), canDelete);
}
use of org.eclipse.jgit.revwalk.RevObject in project gerrit by GerritCodeReview.
the class AutoMerger method merge.
/**
* Perform an auto-merge of the parents of the given merge commit.
*
* @return auto-merge commit or {@code null} if an auto-merge commit couldn't be created. Headers
* of the returned RevCommit are parsed.
*/
public RevCommit merge(Repository repo, RevWalk rw, final ObjectInserter ins, RevCommit merge, ThreeWayMergeStrategy mergeStrategy) throws IOException {
checkArgument(rw.getObjectReader().getCreatedFromInserter() == ins);
InMemoryInserter tmpIns = null;
if (ins instanceof InMemoryInserter) {
// Caller gave us an in-memory inserter, so ensure anything we write from
// this method is visible to them.
tmpIns = (InMemoryInserter) ins;
} else if (!save) {
// If we don't plan on saving results, use a fully in-memory inserter.
// Using just a non-flushing wrapper is not sufficient, since in
// particular DfsInserter might try to write to storage after exceeding an
// internal buffer size.
tmpIns = new InMemoryInserter(rw.getObjectReader());
}
rw.parseHeaders(merge);
String refName = RefNames.refsCacheAutomerge(merge.name());
Ref ref = repo.getRefDatabase().exactRef(refName);
if (ref != null && ref.getObjectId() != null) {
RevObject obj = rw.parseAny(ref.getObjectId());
if (obj instanceof RevCommit) {
return (RevCommit) obj;
}
return commit(repo, rw, tmpIns, ins, refName, obj, merge);
}
ResolveMerger m = (ResolveMerger) mergeStrategy.newMerger(repo, true);
DirCache dc = DirCache.newInCore();
m.setDirCache(dc);
m.setObjectInserter(tmpIns == null ? new NonFlushingWrapper(ins) : tmpIns);
boolean couldMerge;
try {
couldMerge = m.merge(merge.getParents());
} catch (IOException e) {
// It is not safe to continue further down in this method as throwing
// an exception most likely means that the merge tree was not created
// and m.getMergeResults() is empty. This would mean that all paths are
// unmerged and Gerrit UI would show all paths in the patch list.
log.warn("Error attempting automerge " + refName, e);
return null;
}
ObjectId treeId;
if (couldMerge) {
treeId = m.getResultTreeId();
} else {
RevCommit ours = merge.getParent(0);
RevCommit theirs = merge.getParent(1);
rw.parseBody(ours);
rw.parseBody(theirs);
String oursMsg = ours.getShortMessage();
String theirsMsg = theirs.getShortMessage();
String oursName = String.format("HEAD (%s %s)", ours.abbreviate(6).name(), oursMsg.substring(0, Math.min(oursMsg.length(), 60)));
String theirsName = String.format("BRANCH (%s %s)", theirs.abbreviate(6).name(), theirsMsg.substring(0, Math.min(theirsMsg.length(), 60)));
MergeFormatter fmt = new MergeFormatter();
Map<String, MergeResult<? extends Sequence>> r = m.getMergeResults();
Map<String, ObjectId> resolved = new HashMap<>();
for (Map.Entry<String, MergeResult<? extends Sequence>> entry : r.entrySet()) {
MergeResult<? extends Sequence> p = entry.getValue();
try (TemporaryBuffer buf = new TemporaryBuffer.LocalFile(null, 10 * 1024 * 1024)) {
fmt.formatMerge(buf, p, "BASE", oursName, theirsName, UTF_8.name());
buf.close();
try (InputStream in = buf.openInputStream()) {
resolved.put(entry.getKey(), ins.insert(Constants.OBJ_BLOB, buf.length(), in));
}
}
}
DirCacheBuilder builder = dc.builder();
int cnt = dc.getEntryCount();
for (int i = 0; i < cnt; ) {
DirCacheEntry entry = dc.getEntry(i);
if (entry.getStage() == 0) {
builder.add(entry);
i++;
continue;
}
int next = dc.nextEntry(i);
String path = entry.getPathString();
DirCacheEntry res = new DirCacheEntry(path);
if (resolved.containsKey(path)) {
// For a file with content merge conflict that we produced a result
// above on, collapse the file down to a single stage 0 with just
// the blob content, and a randomly selected mode (the lowest stage,
// which should be the merge base, or ours).
res.setFileMode(entry.getFileMode());
res.setObjectId(resolved.get(path));
} else if (next == i + 1) {
// If there is exactly one stage present, shouldn't be a conflict...
res.setFileMode(entry.getFileMode());
res.setObjectId(entry.getObjectId());
} else if (next == i + 2) {
// Two stages suggests a delete/modify conflict. Pick the higher
// stage as the automatic result.
entry = dc.getEntry(i + 1);
res.setFileMode(entry.getFileMode());
res.setObjectId(entry.getObjectId());
} else {
// 3 stage conflict, no resolve above
// Punt on the 3-stage conflict and show the base, for now.
res.setFileMode(entry.getFileMode());
res.setObjectId(entry.getObjectId());
}
builder.add(res);
i = next;
}
builder.finish();
treeId = dc.writeTree(ins);
}
return commit(repo, rw, tmpIns, ins, refName, treeId, merge);
}
Aggregations