Skip to content
Snippets Groups Projects
Commit 8b9b090b authored by Jack MacLauchlan CS2015's avatar Jack MacLauchlan CS2015
Browse files

Merge branch 'issuedir' into 'master'

Issuedir

See merge request !1
parents 684615dc 35c74a45
No related branches found
No related tags found
1 merge request!1Issuedir
Showing
with 524 additions and 142 deletions
......@@ -30,3 +30,6 @@ hs_err_pid*
.project
.classpath
.DS_Store
#maven
target/
......@@ -48,6 +48,17 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.3</version>
</dependency>
</dependencies>
......
......@@ -10,7 +10,7 @@ public class CommandLineInterface {
this.options = new Options();
addOptions();
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("to do", options); //todo
// formatter.printHelp("to do", options); //todo
}
......@@ -33,6 +33,28 @@ public class CommandLineInterface {
.build();
uniqueCommands.addOption(createIssue);
Option showIssue = Option.builder()
.longOpt("show")
.hasArg()
.argName("ID")
.desc("show issue with ID")
.build();
uniqueCommands.addOption(showIssue);
Option ls = Option.builder()
.longOpt("ls")
.desc("list issues")
.build();
uniqueCommands.addOption(ls);
Option comment = Option.builder()
.longOpt("comment")
.hasArgs()
.argName("ID> <MESSAGE")
.numberOfArgs(2)
.desc("comment on issue with given id")
.build();
uniqueCommands.addOption(comment);
// Option createIssue = Option.builder()
// .longOpt("new")
......@@ -58,17 +80,6 @@ public class CommandLineInterface {
.build();
uniqueCommands.addOption(deleteIssue);
Option comment = Option.builder()
.longOpt("comment")
.desc("comment on issue with given id")
.build();
uniqueCommands.addOption(comment);
Option viewIssues = Option.builder()
.longOpt("view")
.desc("view on issue with given id")
.build();
uniqueCommands.addOption(viewIssues);
options.addOptionGroup(uniqueCommands);
......
package command;
import issueData.Comment;
import issueData.IssueRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import java.io.File;
import java.io.IOException;
public class CommandComment implements Command {
private String id;
private String comment;
public CommandComment(String id, String comment) {
this.id = id;
this.comment = comment;
}
@Override
public void execute() {
IssueRepository issueRepository = new IssueRepository();
String author;
try {
Repository repository = new FileRepositoryBuilder()
.setGitDir(new File("/home/jack/Documents/testrepo/.issues"))
.build();
Config config = repository.getConfig();
String name = config.getString("user", null, "name");
String email = config.getString("user", null, "email");
if (name == null || email == null) {
author = "Unknown";
} else {
author = "User " + name + " <" + email + ">";
}
issueRepository.getIssues().forEach(issue -> {
if (id.equals(issue.getOriginalHash())) {
issue.addComment(new Comment(author, comment));
issue.write();
System.out.println("Comment added");
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
package command;
import issue.Issue;
import issueData.Issue;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class CommandCreate implements Command {
private String title;
private String description;
// private String path = "/home/jack/Documents/testrepo/";
private String path = "/home/jack/Documents/issue-worktree";
// private String path = "/home/jack/Documents/testrepo/";
private String path = "/home/jack/Documents/testrepo/.issues";
public CommandCreate(String[] args) {
this.title = args[0];
this.description = args[1];
}
private void writeIssue(Issue issue) {
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(path + issue.getOriginalHash());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(issue);
objectOutputStream.flush();
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void commitAndPush(Issue issue) {
try (Git git = Git.open(new File(path))) {
if (git.getRepository().getBranch().equals("issues")) {
writeIssue(issue);
git.add().addFilepattern(String.valueOf(issue.hashCode())).call();
git.commit().setMessage("issue created: " + issue.hashCode() + " - title: " + issue.getTitle()).call();
} else {
git.checkout().setName("issues").call();
writeIssue(issue);
git.add().addFilepattern(String.valueOf(issue.hashCode())).call();
git.commit().setMessage("issue created: " + issue.hashCode() + " - title: " + issue.getTitle()).call();
}
issue.setCreator(getAuthor(git.getRepository()));
issue.write();
git.add().addFilepattern(String.valueOf(issue.hashCode())).call();
git.commit().setMessage("issue created: " + issue.getOriginalHash() + " - title: " + issue.getTitle()).call();
} catch (GitAPIException | IOException e) {
e.printStackTrace();
}
}
private String getAuthor(Repository repository) {
Config config = repository.getConfig();
String name = config.getString("user", null, "name");
String email = config.getString("user", null, "email");
if (name == null || email == null) {
return "Unknown";
} else {
return "User " + name + " Email:" + email;
}
}
public void execute() {
Issue issue = new Issue(title, description);
commitAndPush(issue);
System.out.println("Issue created");
}
}
......@@ -3,91 +3,34 @@ package command;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import java.io.*;
import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class CommandInit implements Command {
private String path = "/home/jack/Documents/testrepo";
public void createWorkTree() throws IOException {
ProcessBuilder builder = new ProcessBuilder();
builder.command("/home/jack/Documents/ddit/src/main/resources/ignoreStream.sh", "sh", "-c");
builder.directory(new File(path));
Process process = builder.start();
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = 0;
try {
exitCode = process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
assert exitCode == 0;
}
public void execute() {
//problem: files not added to git obv cant be stashed, lost when change branch
String issueRepo = path + "/.issues";
File dir = new File(path);
try (Git git = Git.open(dir)) { //Newly initialized repositories have a peculiarity in that no branch has yet been created.
// RevCommit stash = git.stashCreate().call();
String branch = git.getRepository().getBranch();
git.checkout()
.setCreateBranch(true)
.setOrphan(true)
.setName("issues")
try {
Files.createDirectories(Paths.get(issueRepo));
Git.init()
.setDirectory(new File(issueRepo))
.call();
for (File file : Objects.requireNonNull(dir.listFiles())) {
if (!file.getName().equals(".git")) {
file.delete();
}
}
Git git = Git.open(new File(issueRepo));
Files.createFile(Paths.get(issueRepo + "/.init"));
git.add().setUpdate(true).addFilepattern(".").call();
git.commit().setMessage("initialise issue branch").call();
git.checkout().setName(branch).call();
// createWorkTree();
// git.stashApply().setStashRef(stash.getName()).call();
git.commit().setMessage("initial commit").call();
System.out.println("Issue repository created");
} catch (IOException e) {
System.out.println("Not a git repository - aborting operation");
e.printStackTrace();
} catch (GitAPIException e) {
} catch (IOException | GitAPIException e) {
e.printStackTrace();
}
}
private static class StreamGobbler implements Runnable {
private InputStream inputStream;
private Consumer<String> consumer;
public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
this.inputStream = inputStream;
this.consumer = consumer;
}
@Override
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
}
}
}
// Ref headRef = git.getRepository().getRef( Constants.HEAD );
//if( headRef == null || headRef.getObjectId() == null ) {
// // no commit yet
// }
// System.out.println(System.getProperty("user.dir"));
\ No newline at end of file
}
\ No newline at end of file
package command;
import issueData.IssueRepository;
public class CommandLs implements Command {
@Override
public void execute() {
IssueRepository issueRepository = new IssueRepository();
issueRepository.getIssues().forEach(System.out::println);
}
}
......@@ -23,16 +23,26 @@ public class CommandSelector {
command = createIssue(userInput.getOptionValues("new"));
} else if (userInput.hasOption("init")) {
command = init();
} else if (userInput.hasOption("ls")) {
command = ls();
} else if (userInput.hasOption("show")) {
command = show(userInput.getOptionValue("show"));
} else if (userInput.hasOption("comment")) {
command = comment(userInput.getOptionValues("comment"));
} else {
command = nullCommand();
}
command.execute();
} catch (ParseException e) {
e.printStackTrace(); //todo
e.printStackTrace();
}
}
private Command comment(String[] args) {
return new CommandComment(args[0], args[1]);
}
private Command init() {
return new CommandInit();
}
......@@ -45,7 +55,12 @@ public class CommandSelector {
return new CommandCreate(args);
}
private Command pushIssue() {
return new CommandPush();
private Command ls() {
return new CommandLs();
}
private Command show(String id) {
return new CommandShow(id);
}
}
package command;
import issueData.IssueRepository;
public class CommandShow implements Command {
private String id;
public CommandShow(String id) {
this.id = id;
}
@Override
public void execute() {
IssueRepository repository = new IssueRepository();
repository.getIssues().forEach(issue -> {
if (issue.getOriginalHash().equals(id)) {
String status = issue.isopen() ? "Open" : "Closed";
System.out.println("Issue title: " + issue.getTitle() + "\n" +
"Issue Description: " + issue.getDescription() + "\n" +
"Status: " + status + "\n" +
"Creator: " + issue.getCreator() + "\n" +
"Last edited: " + issue.getEdited() + "\n" +
"Creation time: " + issue.getCreationTime());
if (issue.getComments().isEmpty()) {
System.out.println("\nNo comments on this issue");
} else {
System.out.println("\nComments:\n");
issue.getComments().forEach(comment -> System.out.println("Author: " + comment.getAuthor() + "\n" + comment.getMessage() + "\n"));
}
}
});
}
}
package issue;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class IssueHistory implements Serializable {
private List<Issue> issueHistory;
public IssueHistory(){
this.issueHistory = new ArrayList<>();
}
}
package issueData;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.Objects;
public class Comment {
private String hash;
private String author;
private String message;
private long creationTime;
public Comment(String author, String message) {
this.author = author;
this.message = message;
this.creationTime = System.currentTimeMillis();
this.hash = DigestUtils.sha256Hex(author + message + creationTime);
}
public Comment() {
}
public String getHash() {
return hash;
}
public void setHash(String hash) {
this.hash = hash;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getCreationTime() {
return creationTime;
}
public void setCreationTime(long creationTime) {
this.creationTime = creationTime;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Comment comment = (Comment) o;
return creationTime == comment.creationTime &&
Objects.equals(hash, comment.hash) &&
Objects.equals(author, comment.author) &&
Objects.equals(message, comment.message);
}
@Override
public int hashCode() {
return Objects.hash(hash, author, message, creationTime);
}
}
package issue;
package issueData;
import java.io.Serializable;
import org.apache.commons.codec.digest.DigestUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Issue implements Serializable {
public class Issue {
private static final long serialVersionUID = 1L;
private String title;
private String description;
private String creator;
private String originalHash;
private List<Comment> comments;
private boolean status;
private long creationTime;
private long edited;
public Issue(String title, String description) {
this.title = title;
this.description = description;
this.status = true;
long time = System.currentTimeMillis();
this.creationTime = time + 1;
this.creationTime = time + 1; //Lamport timestamps
this.edited = time + 1;
this.originalHash = String.valueOf(hashCode());
this.originalHash = DigestUtils.sha256Hex(title + description + creationTime);
this.comments = new ArrayList<>();
}
public Issue() {
comments = new ArrayList<>();
}
private void edited() {
edited = System.currentTimeMillis();
}
public long getCreationTime() {
return creationTime;
}
public void setCreationTime(long creationTime) {
this.creationTime = creationTime;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
edited();
}
public String getOriginalHash() {
return originalHash;
}
public void setOriginalHash(String originalHash) {
this.originalHash = originalHash;
}
public void addComment(Comment comment) {
comments.add(comment);
}
public List<Comment> getComments() {
return comments;
}
public long getEdited() {
return edited;
}
public void setEdited(long edited) {
this.edited = edited;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
edited();
}
private void edited(){
edited = System.currentTimeMillis();
public String getCreator() {
return creator;
}
public String getTitle(){
return this.title;
public void setCreator(String creator) {
this.creator = creator;
}
public boolean isopen() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public void write() {
IssueWriter writer = new IssueWriter(this);
writer.write();
}
@Override
......@@ -47,20 +112,19 @@ public class Issue implements Serializable {
Issue issue = (Issue) o;
return creationTime == issue.creationTime &&
Objects.equals(title, issue.title) &&
Objects.equals(description, issue.description);
Objects.equals(description, issue.description) &&
Objects.equals(creator, issue.creator) &&
Objects.equals(originalHash, issue.originalHash);
}
@Override
public int hashCode() {
return Objects.hash(title, description, creationTime);
return Objects.hash(title, description, creator, originalHash, creationTime);
}
@Override
public String toString() {
return "Title: " + title + " Description: " + description;
return "Hash: " + originalHash + " Title: " + title;
}
public String getOriginalHash() {
return originalHash;
}
}
package issueData;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class IssueRepository {
private List<Issue> issues;
public IssueRepository() {
this.issues = new ArrayList<>();
readAllIssues();
}
public List<Issue> getIssues() {
return issues;
}
private void readAllIssues() {
ObjectMapper mapper = new ObjectMapper();
File[] directories = new File("/home/jack/Documents/testrepo/.issues/").listFiles(File::isDirectory);
Arrays.stream(Objects.requireNonNull(directories)).forEach(issueDir -> {
if (issueDir.getName().equals(".git")) return;
try {
String originalHash = issueDir.getName();
String title = mapper.readValue(new File(issueDir.getAbsolutePath() + "/title"), String.class);
String description = mapper.readValue(new File(issueDir.getAbsolutePath() + "/description"), String.class);
String creator = mapper.readValue(new File(issueDir.getAbsolutePath() + "/creator"), String.class);
boolean status = mapper.readValue(new File(issueDir.getAbsolutePath() + "/status"), boolean.class);
long creationTime = mapper.readValue(new File(issueDir.getAbsolutePath() + "/creationTime"), long.class);
long edited = mapper.readValue(new File(issueDir.getAbsolutePath() + "/editedTime"), long.class);
Issue issue = new Issue();
issue.setTitle(title);
issue.setDescription(description);
issue.setCreator(creator);
issue.setOriginalHash(originalHash);
issue.setStatus(status);
issue.setCreationTime(creationTime);
issue.setEdited(edited);
String commentDirPath = "/home/jack/Documents/testrepo/.issues/" + issueDir.getName() + "/comments/";
File[] commentDirs = new File(commentDirPath).listFiles((File::isDirectory));
for (File commentDir : Objects.requireNonNull(commentDirs)) {
Comment comment = new Comment();
String commentHash = commentDir.getName();
String author = mapper.readValue(new File(commentDirPath + commentDir.getName() + "/author"), String.class);
String message = mapper.readValue(new File(commentDirPath + commentDir.getName() + "/message"), String.class);
long commentTime = mapper.readValue(new File(commentDirPath + commentDir.getName() + "/creationTime"), long.class);
comment.setHash(commentHash);
comment.setAuthor(author);
comment.setMessage(message);
comment.setCreationTime(commentTime);
issue.addComment(comment);
}
issues.add(issue);
} catch (IOException e) {
e.printStackTrace();
}
});
}
}
package issueData;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class IssueWriter {
private Issue issue;
public IssueWriter(Issue issue) {
this.issue = issue;
}
public void write() {
String path = "/home/jack/Documents/testrepo/.issues/" + issue.getOriginalHash() + "/";
Path commentDir = Paths.get(path + "comments/");
try {
Files.createDirectories(commentDir);
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(new File(path + "title"), issue.getTitle());
mapper.writeValue(new File(path + "description"), issue.getDescription());
mapper.writeValue(new File(path + "creator"), issue.getCreator());
mapper.writeValue(new File(path + "status"), issue.isopen());
mapper.writeValue(new File(path + "creationTime"), issue.getCreationTime());
mapper.writeValue(new File(path + "editedTime"), issue.getEdited());
for (Comment comment : issue.getComments()) {
String commentPath = commentDir + "/" + comment.getHash() + "/";
Files.createDirectories(Paths.get(commentPath));
mapper.writeValue(new File(commentPath + "author"), comment.getAuthor());
mapper.writeValue(new File(commentPath + "message"), comment.getMessage());
mapper.writeValue(new File(commentPath + "creationTime"), comment.getCreationTime());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package jgit;
public class JGit {
}
......@@ -11,8 +11,6 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CommandInitTest {
Path dir;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment