aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/api
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/api')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java63
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java30
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java20
3 files changed, 80 insertions, 33 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
index 583767af3f..58b339a237 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ApplyCommand.java
@@ -22,6 +22,7 @@ import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.zip.InflaterInputStream;
@@ -38,12 +39,14 @@ import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.FileModeCache;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectStream;
@@ -65,6 +68,7 @@ import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.StringUtils;
+import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.TemporaryBuffer.LocalFile;
import org.eclipse.jgit.util.io.BinaryDeltaInputStream;
@@ -72,6 +76,12 @@ import org.eclipse.jgit.util.io.BinaryHunkInputStream;
import org.eclipse.jgit.util.io.EolStreamTypeUtil;
import org.eclipse.jgit.util.sha1.SHA1;
+import static org.eclipse.jgit.diff.DiffEntry.ChangeType.ADD;
+import static org.eclipse.jgit.diff.DiffEntry.ChangeType.COPY;
+import static org.eclipse.jgit.diff.DiffEntry.ChangeType.DELETE;
+import static org.eclipse.jgit.diff.DiffEntry.ChangeType.MODIFY;
+import static org.eclipse.jgit.diff.DiffEntry.ChangeType.RENAME;
+
/**
* Apply a patch to files and/or to the index.
*
@@ -131,30 +141,34 @@ public class ApplyCommand extends GitCommand<ApplyResult> {
throw new PatchFormatException(p.getErrors());
}
Repository repository = getRepository();
+ FileModeCache directoryCache = new FileModeCache(repo);
DirCache cache = repository.readDirCache();
for (FileHeader fh : p.getFiles()) {
ChangeType type = fh.getChangeType();
File f = null;
+ verifyExistence(fh,
+ new File(repo.getWorkTree(), fh.getOldPath()),
+ new File(repo.getWorkTree(), fh.getNewPath()));
switch (type) {
case ADD:
- f = getFile(fh.getNewPath(), true);
+ f = getFile(fh.getNewPath(), true, directoryCache);
apply(repository, fh.getNewPath(), cache, f, fh);
break;
case MODIFY:
- f = getFile(fh.getOldPath(), false);
+ f = getFile(fh.getOldPath(), false, directoryCache);
apply(repository, fh.getOldPath(), cache, f, fh);
break;
case DELETE:
- f = getFile(fh.getOldPath(), false);
+ f = getFile(fh.getOldPath(), false, directoryCache);
if (!f.delete())
throw new PatchApplyException(MessageFormat.format(
JGitText.get().cannotDeleteFile, f));
break;
case RENAME:
- f = getFile(fh.getOldPath(), false);
- File dest = getFile(fh.getNewPath(), false);
+ f = getFile(fh.getOldPath(), false, directoryCache);
+ File dest = getFile(fh.getNewPath(), false, directoryCache);
try {
- FileUtils.mkdirs(dest.getParentFile(), true);
+ directoryCache.safeCreateParentDirectory(fh.getNewPath(), dest.getParentFile(), false);
FileUtils.rename(f, dest,
StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
@@ -164,9 +178,9 @@ public class ApplyCommand extends GitCommand<ApplyResult> {
apply(repository, fh.getOldPath(), cache, dest, fh);
break;
case COPY:
- f = getFile(fh.getOldPath(), false);
- File target = getFile(fh.getNewPath(), false);
- FileUtils.mkdirs(target.getParentFile(), true);
+ f = getFile(fh.getOldPath(), false, directoryCache);
+ File target = getFile(fh.getNewPath(), false, directoryCache);
+ directoryCache.safeCreateParentDirectory(fh.getNewPath(), target.getParentFile(), false);
Files.copy(f.toPath(), target.toPath());
apply(repository, fh.getOldPath(), cache, target, fh);
}
@@ -179,13 +193,40 @@ public class ApplyCommand extends GitCommand<ApplyResult> {
return r;
}
- private File getFile(String path, boolean create)
+ private void verifyExistence(FileHeader fh, File src, File dest)
+ throws IOException, PatchApplyException {
+ boolean srcShouldExist = Arrays
+ .asList(new ChangeType[] { MODIFY, DELETE, RENAME, COPY })
+ .contains(fh.getChangeType());
+ boolean destShouldNotExist = Arrays
+ .asList(new ChangeType[] { ADD, RENAME, COPY })
+ .contains(fh.getChangeType());
+ if (srcShouldExist && !validGitPath(fh.getOldPath())) {
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().applyPatchSourceInvalid, fh.getOldPath()));
+ }
+ if (destShouldNotExist && !validGitPath(fh.getNewPath())) {
+ throw new PatchApplyException(MessageFormat.format(
+ JGitText.get().applyPatchDestInvalid, fh.getNewPath()));
+ }
+ }
+
+ private boolean validGitPath(String path) {
+ try {
+ SystemReader.getInstance().checkPath(path);
+ return true;
+ } catch (CorruptObjectException e) {
+ return false;
+ }
+ }
+
+ private File getFile(String path, boolean create, FileModeCache directoryCache)
throws PatchApplyException {
File f = new File(getRepository().getWorkTree(), path);
if (create) {
try {
File parent = f.getParentFile();
- FileUtils.mkdirs(parent, true);
+ directoryCache.safeCreateParentDirectory(path, parent, false);
FileUtils.createNewFile(f);
} catch (IOException e) {
throw new PatchApplyException(MessageFormat.format(
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index 847ab0a9a8..8edae5a580 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
- * Copyright (C) 2011, 2020 Matthias Sohn <matthias.sohn@sap.com> and others
+ * Copyright (C) 2011, 2023 Matthias Sohn <matthias.sohn@sap.com> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -28,6 +28,7 @@ import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
+import org.eclipse.jgit.dircache.Checkout;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheCheckout.CheckoutMetadata;
@@ -411,6 +412,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
protected CheckoutCommand checkoutPaths() throws IOException,
RefNotFoundException {
actuallyModifiedPaths = new HashSet<>();
+ Checkout checkout = new Checkout(repo).setRecursiveDeletion(true);
DirCache dc = repo.lockDirCache();
try (RevWalk revWalk = new RevWalk(repo);
TreeWalk treeWalk = new TreeWalk(repo,
@@ -419,10 +421,10 @@ public class CheckoutCommand extends GitCommand<Ref> {
if (!checkoutAllPaths)
treeWalk.setFilter(PathFilterGroup.createFromStrings(paths));
if (isCheckoutIndex())
- checkoutPathsFromIndex(treeWalk, dc);
+ checkoutPathsFromIndex(treeWalk, dc, checkout);
else {
RevCommit commit = revWalk.parseCommit(getStartPointObjectId());
- checkoutPathsFromCommit(treeWalk, dc, commit);
+ checkoutPathsFromCommit(treeWalk, dc, commit, checkout);
}
} finally {
try {
@@ -439,7 +441,8 @@ public class CheckoutCommand extends GitCommand<Ref> {
return this;
}
- private void checkoutPathsFromIndex(TreeWalk treeWalk, DirCache dc)
+ private void checkoutPathsFromIndex(TreeWalk treeWalk, DirCache dc,
+ Checkout checkout)
throws IOException {
DirCacheIterator dci = new DirCacheIterator(dc);
treeWalk.addTree(dci);
@@ -465,8 +468,9 @@ public class CheckoutCommand extends GitCommand<Ref> {
if (stage > DirCacheEntry.STAGE_0) {
if (checkoutStage != null) {
if (stage == checkoutStage.number) {
- checkoutPath(ent, r, new CheckoutMetadata(
- eolStreamType, filterCommand));
+ checkoutPath(ent, r, checkout, path,
+ new CheckoutMetadata(eolStreamType,
+ filterCommand));
actuallyModifiedPaths.add(path);
}
} else {
@@ -475,8 +479,9 @@ public class CheckoutCommand extends GitCommand<Ref> {
throw new JGitInternalException(e.getMessage(), e);
}
} else {
- checkoutPath(ent, r, new CheckoutMetadata(eolStreamType,
- filterCommand));
+ checkoutPath(ent, r, checkout, path,
+ new CheckoutMetadata(eolStreamType,
+ filterCommand));
actuallyModifiedPaths.add(path);
}
}
@@ -488,7 +493,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
private void checkoutPathsFromCommit(TreeWalk treeWalk, DirCache dc,
- RevCommit commit) throws IOException {
+ RevCommit commit, Checkout checkout) throws IOException {
treeWalk.addTree(commit.getTree());
final ObjectReader r = treeWalk.getObjectReader();
DirCacheEditor editor = dc.editor();
@@ -510,7 +515,7 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
ent.setObjectId(blobId);
ent.setFileMode(mode);
- checkoutPath(ent, r,
+ checkoutPath(ent, r, checkout, path,
new CheckoutMetadata(eolStreamType, filterCommand));
actuallyModifiedPaths.add(path);
}
@@ -520,10 +525,9 @@ public class CheckoutCommand extends GitCommand<Ref> {
}
private void checkoutPath(DirCacheEntry entry, ObjectReader reader,
- CheckoutMetadata checkoutMetadata) {
+ Checkout checkout, String path, CheckoutMetadata checkoutMetadata) {
try {
- DirCacheCheckout.checkoutEntry(repo, entry, reader, true,
- checkoutMetadata);
+ checkout.checkout(entry, checkoutMetadata, reader, path);
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutConflictWithFile,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
index 1004d3e50f..e4157286f1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/StashApplyCommand.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2021 GitHub Inc. and others
+ * Copyright (C) 2012, 2023 GitHub Inc. and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -23,6 +23,7 @@ import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.StashApplyFailureException;
import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
+import org.eclipse.jgit.dircache.Checkout;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheCheckout;
@@ -382,6 +383,7 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
private void resetUntracked(RevTree tree) throws CheckoutConflictException,
IOException {
Set<String> actuallyModifiedPaths = new HashSet<>();
+ Checkout checkout = new Checkout(repo).setRecursiveDeletion(true);
// TODO maybe NameConflictTreeWalk ?
try (TreeWalk walk = new TreeWalk(repo)) {
walk.addTree(tree);
@@ -405,17 +407,17 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
FileTreeIterator fIter = walk
.getTree(1, FileTreeIterator.class);
+ String gitPath = entry.getPathString();
if (fIter != null) {
if (fIter.isModified(entry, true, reader)) {
// file exists and is dirty
- throw new CheckoutConflictException(
- entry.getPathString());
+ throw new CheckoutConflictException(gitPath);
}
}
- checkoutPath(entry, reader,
+ checkoutPath(entry, gitPath, reader, checkout,
new CheckoutMetadata(eolStreamType, null));
- actuallyModifiedPaths.add(entry.getPathString());
+ actuallyModifiedPaths.add(gitPath);
}
} finally {
if (!actuallyModifiedPaths.isEmpty()) {
@@ -425,11 +427,11 @@ public class StashApplyCommand extends GitCommand<ObjectId> {
}
}
- private void checkoutPath(DirCacheEntry entry, ObjectReader reader,
- CheckoutMetadata checkoutMetadata) {
+ private void checkoutPath(DirCacheEntry entry, String gitPath,
+ ObjectReader reader,
+ Checkout checkout, CheckoutMetadata checkoutMetadata) {
try {
- DirCacheCheckout.checkoutEntry(repo, entry, reader, true,
- checkoutMetadata);
+ checkout.checkout(entry, checkoutMetadata, reader, gitPath);
} catch (IOException e) {
throw new JGitInternalException(MessageFormat.format(
JGitText.get().checkoutConflictWithFile,