Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

146: git-webrev: Add support for file list argument #275

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -36,6 +36,7 @@
import java.nio.file.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class GitWebrev {
private static void clearDirectory(Path directory) {
@@ -134,7 +135,13 @@ private static void generate(String[] args) throws IOException {
.helptext("Print the version of this tool")
.optional());

var parser = new ArgumentParser("git webrev", flags);
var inputs = List.of(
Input.position(0)
.describe("FILE")
.singular()
.optional());

var parser = new ArgumentParser("git webrev", flags, inputs);
var arguments = parser.parse(args);

var version = Version.fromManifest().orElse("unknown");
@@ -246,13 +253,19 @@ private static void generate(String[] args) throws IOException {
clearDirectory(output);
}

List<Path> files = List.of();
if (arguments.at(0).isPresent()) {
var path = arguments.at(0).via(Path::of);
files = Files.readAllLines(path).stream().map(Path::of).collect(Collectors.toList());
}
Webrev.repository(repo)
.output(output)
.title(title)
.upstream(upstream)
.username(username)
.issue(issue)
.version(version)
.files(files)
.generate(rev);
}

@@ -189,10 +189,18 @@ public Diff diff(Hash base, Hash head) throws IOException {
return null;
}

public Diff diff(Hash base, Hash head, List<Path> files) throws IOException {
return null;
}

public Diff diff(Hash head) throws IOException {
return null;
}

public Diff diff(Hash head, List<Path> files) throws IOException {
return null;
}

public List<String> config(String key) throws IOException {
return null;
}
@@ -77,7 +77,9 @@ default List<FileEntry> files(Hash h, Path... paths) throws IOException {
void dump(FileEntry entry, Path to) throws IOException;
List<StatusEntry> status(Hash from, Hash to) throws IOException;
Diff diff(Hash base, Hash head) throws IOException;
Diff diff(Hash base, Hash head, List<Path> files) throws IOException;
Diff diff(Hash head) throws IOException;
Diff diff(Hash head, List<Path> files) throws IOException;
List<String> config(String key) throws IOException;
Repository copyTo(Path destination) throws IOException;
String pullPath(String remote) throws IOException;
@@ -819,11 +819,21 @@ public List<StatusEntry> status(Hash from, Hash to) throws IOException {

@Override
public Diff diff(Hash from) throws IOException {
return diff(from, null);
return diff(from, List.of());
}

@Override
public Diff diff(Hash from, List<Path> files) throws IOException {
return diff(from, null, files);
}

@Override
public Diff diff(Hash from, Hash to) throws IOException {
return diff(from, to, List.of());
}

@Override
public Diff diff(Hash from, Hash to, List<Path> files) throws IOException {
var cmd = new ArrayList<>(List.of("git", "diff", "--patch",
"--find-renames=99%",
"--find-copies=99%",
@@ -838,6 +848,13 @@ public Diff diff(Hash from, Hash to) throws IOException {
cmd.add(to.hex());
}

if (files != null && !files.isEmpty()) {
cmd.add("--");
for (var file : files) {
cmd.add(file.toString());
}
}

var p = start(cmd);
try {
var patches = UnifiedDiffParser.parseGitRaw(p.getInputStream());
@@ -736,11 +736,21 @@ public void revert(Hash parent) throws IOException {

@Override
public Diff diff(Hash from) throws IOException {
return diff(from, null);
return diff(from, List.of());
}

@Override
public Diff diff(Hash from, List<Path> files) throws IOException {
return diff(from, null, files);
}

@Override
public Diff diff(Hash from, Hash to) throws IOException {
return diff(from, to, List.of());
}

@Override
public Diff diff(Hash from, Hash to, List<Path> files) throws IOException {
var ext = Files.createTempFile("ext", ".py");
copyResource(EXT_PY, ext);

@@ -750,6 +760,11 @@ public Diff diff(Hash from, Hash to) throws IOException {
cmd.add(to.hex());
}

if (files != null) {
var filenames = files.stream().map(Path::toString).collect(Collectors.toList());
cmd.add("--files=" + String.join(",", filenames));
}

var p = start(cmd);
try {
var patches = UnifiedDiffParser.parseGitRaw(p.getInputStream());
@@ -155,8 +155,8 @@ def decorator(func):
revsingle = mercurial.cmdutil.revsingle
revrange = mercurial.cmdutil.revrange

@command(b'diff-git-raw', [(b'', b'patch', False, b'')], b'hg diff-git-raw rev1 [rev2]')
def diff_git_raw(ui, repo, rev1, rev2=None, **opts):
@command(b'diff-git-raw', [(b'', b'patch', False, b''), (b'', b'files', b'', b'')], b'hg diff-git-raw rev1 [rev2]')
def diff_git_raw(ui, repo, rev1, rev2=None, *files, **opts):
ctx1 = revsingle(repo, rev1)

if rev2 != None:
@@ -167,6 +167,14 @@ def diff_git_raw(ui, repo, rev1, rev2=None, **opts):
status = repo.status(ctx1)

modified, added, removed = [set(l) for l in status[:3]]

files = opts['files']
if files != b'':
wanted = set(files.split(b','))
modified = modified & wanted
added = added & wanted
removed = removed & wanted

_diff_git_raw(repo, ctx1, ctx2, modified, added, removed, opts['patch'])

@command(b'log-git', [(b'', b'reverse', False, b''), (b'l', b'limit', -1, b'')], b'hg log-git <revisions>')
@@ -1944,4 +1944,54 @@ void testAnnotateTagOnEmptyRepo(VCS vcs) throws IOException {
assertEquals(Optional.empty(), repo.annotate(new Tag("unknown")));
}
}

@ParameterizedTest
@EnumSource(VCS.class)
void testDiffWithFileList(VCS vcs) throws IOException {
try (var dir = new TemporaryDirectory(false)) {
var repo = Repository.init(dir.path(), vcs);
var readme = repo.root().resolve("README");
Files.writeString(readme, "Hello\n");
repo.add(readme);

var contribute = repo.root().resolve("CONTRIBUTE");
Files.writeString(contribute, "1. Make changes\n");
repo.add(contribute);

var first = repo.commit("Added README and CONTRIBUTE", "duke", "duke@openjdk.org");
Files.writeString(readme, "World\n", WRITE, APPEND);
Files.writeString(contribute, "2. Run git commit", WRITE, APPEND);

var diff = repo.diff(first, List.of(Path.of("README")));
assertEquals(1, diff.added());
assertEquals(0, diff.modified());
assertEquals(0, diff.removed());
var patches = diff.patches();
assertEquals(1, patches.size());
var patch = patches.get(0);
assertTrue(patch.isTextual());
assertTrue(patch.status().isModified());
assertEquals(Path.of("README"), patch.source().path().get());
assertEquals(Path.of("README"), patch.target().path().get());

repo.add(readme);
repo.add(contribute);
var second = repo.commit("Updates to both README and CONTRIBUTE", "duke", "duke@openjdk.org");

diff = repo.diff(first, second, List.of(Path.of("CONTRIBUTE")));
assertEquals(1, diff.added());
assertEquals(0, diff.modified());
assertEquals(0, diff.removed());
patches = diff.patches();
assertEquals(1, patches.size());
patch = patches.get(0);
assertTrue(patch.isTextual());
assertTrue(patch.status().isModified());
assertEquals(Path.of("CONTRIBUTE"), patch.source().path().get());
assertEquals(Path.of("CONTRIBUTE"), patch.target().path().get());

diff = repo.diff(first, second, List.of(Path.of("DOES_NOT_EXIST")));
assertEquals(0, diff.patches().size());
}
}
}
@@ -61,6 +61,7 @@ public static class Builder {
private String branch;
private String issue;
private String version;
private List<Path> files = List.of();

Builder(ReadOnlyRepository repository, Path output) {
this.repository = repository;
@@ -102,6 +103,11 @@ public Builder version(String version) {
return this;
}

public Builder files(List<Path> files) {
this.files = files;
return this;
}

public void generate(Hash tailEnd) throws IOException {
generate(tailEnd, null);
}
@@ -114,9 +120,36 @@ public void generate(Hash tailEnd, Hash head) throws IOException {
copyResource(CSS);
copyResource(ICON);

var diff = head == null ? repository.diff(tailEnd) : repository.diff(tailEnd, head);
var diff = head == null ?
repository.diff(tailEnd, files) :
repository.diff(tailEnd, head, files);
var patchFile = output.resolve(Path.of(title).getFileName().toString() + ".patch");

var patches = diff.patches();
if (files != null && !files.isEmpty()) {
// Sort the patches according to how they are listed in the `files` list.
var byTargetPath = new HashMap<Path, Patch>();
var bySourcePath = new HashMap<Path, Patch>();
for (var patch : patches) {
if (patch.target().path().isPresent()) {
byTargetPath.put(patch.target().path().get(), patch);
} else {
bySourcePath.put(patch.source().path().get(), patch);
}
}

var sorted = new ArrayList<Patch>();
for (var file : files) {
if (byTargetPath.containsKey(file)) {
sorted.add(byTargetPath.get(file));
} else if (bySourcePath.containsKey(file)) {
sorted.add(bySourcePath.get(file));
} else {
throw new IOException("Filename not present in diff: " + file);
}
}
patches = sorted;
}

var modified = new ArrayList<Integer>();
for (var i = 0; i < patches.size(); i++) {