-
Notifications
You must be signed in to change notification settings - Fork 0
Java06. ДЗ 01, Егоров Антон #6
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,7 @@ | ||
| # java_homeworks | ||
| ## Система контроля версий | ||
| Для запуска системы контроля версий выполните | ||
| ``` | ||
|
|
||
| mvn exec:java -Dexec.mainClass=hw_git.GitCli -Dexec.args="commit commessage testdir/file1" | ||
|
|
||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
|
|
||
| <groupId>1</groupId> | ||
| <artifactId>hw_git_1</artifactId> | ||
| <version>0.0.1-SNAPSHOT</version> | ||
| <packaging>jar</packaging> | ||
|
|
||
| <name>hw_git_1</name> | ||
| <url>http://maven.apache.org</url> | ||
|
|
||
| <properties> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <artifactId>maven-compiler-plugin</artifactId> | ||
| <configuration> | ||
| <source>1.8</source> | ||
| <target>1.8</target> | ||
| <encoding>UTF-8</encoding> | ||
| </configuration> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
| <dependencies> | ||
| <!-- https://mvnrepository.com/artifact/junit/junit --> | ||
| <dependency> | ||
| <groupId>junit</groupId> | ||
| <artifactId>junit</artifactId> | ||
| <version>4.12</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
|
|
||
|
|
||
| <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> | ||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-core</artifactId> | ||
| <version>2.9.6</version> | ||
| </dependency> | ||
|
|
||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-annotations</artifactId> | ||
| <version>2.9.6</version> | ||
| </dependency> | ||
|
|
||
| <dependency> | ||
| <groupId>com.fasterxml.jackson.core</groupId> | ||
| <artifactId>jackson-databind</artifactId> | ||
| <version>2.9.6</version> | ||
| </dependency> | ||
|
|
||
| <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io --> | ||
| <dependency> | ||
| <groupId>org.apache.commons</groupId> | ||
| <artifactId>commons-io</artifactId> | ||
| <version>1.3.2</version> | ||
| </dependency> | ||
| </dependencies> | ||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package hw_git; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.Arrays; | ||
|
|
||
| import com.fasterxml.jackson.core.JsonGenerationException; | ||
| import com.fasterxml.jackson.databind.JsonMappingException; | ||
|
|
||
| public class GitCli { | ||
| public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException { | ||
|
|
||
| GitCore core = new GitCore(); | ||
| int revision; | ||
|
|
||
| try { | ||
| switch (args[0]) { | ||
| case "init": | ||
| core.makeInit(); | ||
| break; | ||
| case "commit": | ||
| System.out.println("Commiting..."); | ||
| core.makeCommit(args[1], Arrays.copyOfRange(args, 2, args.length)); | ||
| System.out.println("Commit made at revision " + core.getCurrentRevision()); | ||
| break; | ||
| case "checkout": | ||
| revision = Integer.parseInt(args[1]); | ||
| System.out.println("Check out to revision " + revision); | ||
| core.makeCheckout(revision); | ||
| break; | ||
| case "reset": | ||
| revision = Integer.parseInt(args[1]); | ||
| System.out.println("Performing reset to revision " + revision); | ||
| core.makeReset(revision); | ||
| break; | ||
| case "log": | ||
| revision = args.length == 2 ? Integer.parseInt(args[1]) : -1; | ||
| System.out.println("Log: " + core.getLog(revision)); | ||
| break; | ||
| default: | ||
| System.out.println("Unknown argument: " + args[0]); | ||
| } | ||
| } catch (UnversionedException e) { | ||
| System.out.println("This directory is not versioned"); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| package hw_git; | ||
|
|
||
| import java.io.File; | ||
| import java.io.IOException; | ||
| import java.nio.file.Files; | ||
| import java.nio.file.Path; | ||
| import java.nio.file.Paths; | ||
| import java.sql.Timestamp; | ||
| import java.util.ArrayList; | ||
| import java.util.Iterator; | ||
| import java.util.Map; | ||
| import java.util.Map.Entry; | ||
|
|
||
| import com.fasterxml.jackson.core.JsonGenerationException; | ||
| import com.fasterxml.jackson.core.JsonParseException; | ||
| import com.fasterxml.jackson.databind.JsonMappingException; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
|
|
||
| public class GitCore { | ||
| private RepInformation inform = null; | ||
| private Path informPath = null; | ||
| private final String infoFileName = ".myGitData"; | ||
| private final String storageFolder = ".mygitdata"; | ||
|
|
||
| void findRepInformation() throws JsonParseException, JsonMappingException, IOException, UnversionedException { | ||
| RepInformation result = null; | ||
| Path p = Paths.get(""); | ||
|
|
||
| while (p != null && !Files.exists(p.resolve(infoFileName))) { | ||
| p = p.getParent(); | ||
| } | ||
|
|
||
| if (p != null) { | ||
| ObjectMapper omapper = new ObjectMapper(); | ||
| result = omapper.readValue(p.resolve(infoFileName).toFile(), RepInformation.class); | ||
| } | ||
|
|
||
| if (result == null) { | ||
| throw new UnversionedException(); | ||
| } | ||
| inform = result; | ||
| informPath = p; | ||
| } | ||
|
|
||
| private void updateRepInformation() throws JsonGenerationException, JsonMappingException, IOException { | ||
| ObjectMapper omapper = new ObjectMapper(); | ||
| System.out.println("writing to path: " + informPath.toString()); | ||
| omapper.writeValue(informPath.resolve(infoFileName).toFile(), inform); | ||
| } | ||
|
|
||
| void makeInit() throws JsonGenerationException, JsonMappingException, IOException, UnversionedException { | ||
| try { | ||
| findRepInformation(); | ||
| } catch (UnversionedException e) { | ||
| //ObjectMapper omapper = new ObjectMapper(); | ||
| //omapper.writeValue(Paths.get("").resolve(filename).toFile(), new RepInformation()); | ||
| informPath = Paths.get(""); | ||
| inform = new RepInformation(); | ||
| //inform.allFiles.put(Paths.get(""), 0); | ||
| updateRepInformation(); | ||
| System.out.println("Ok."); | ||
| } | ||
| } | ||
|
|
||
| void increaseRevisionNumber() { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. private, можно заинлайнить, т.к. всего одно использование и метод однострочный |
||
| inform.revision++; | ||
| } | ||
|
|
||
| private Path getPathRealRelative(String filename) { | ||
| return informPath.relativize(Paths.get("")).resolve(filename); | ||
| } | ||
|
|
||
| private Path getStoragePath(String filename, int revision) { | ||
| Path rel = getPathRealRelative(filename); | ||
| String fname = rel.getFileName().toString(); | ||
|
|
||
| rel = rel.getParent(); | ||
|
|
||
| Path storage = informPath.resolve(storageFolder).resolve(rel).resolve(fname + revision); | ||
|
|
||
| return storage; | ||
| } | ||
|
|
||
| private void addFile(String filename) throws IOException { | ||
| int revision = inform.revision; | ||
| Path storage = getStoragePath(filename, revision); | ||
| storage.getParent().toFile().mkdirs(); | ||
| //System.out.println("trying write file to " + storage); | ||
| Files.copy(Paths.get("").resolve(filename), getStoragePath(filename, revision)); | ||
| ArrayList<Integer> revisions = inform.allFiles.get(getPathRealRelative(filename).toString()); | ||
| if (revisions == null) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. см computeIfAbsent (идея подсвечивает, эклипс молчит?) |
||
| revisions = new ArrayList<>(); | ||
| inform.allFiles.put(getPathRealRelative(filename).toString(), revisions); | ||
| } | ||
| revisions.add(revision); | ||
| } | ||
|
|
||
| void makeCommit(String message, String[] filenames) throws IOException, UnversionedException { | ||
| findRepInformation(); | ||
| increaseRevisionNumber(); | ||
| inform.commitMessages.add(message); | ||
| inform.timestamps.add(new Timestamp(System.currentTimeMillis())); | ||
| for (String fname : filenames) { | ||
| addFile(fname); | ||
| } | ||
| updateRepInformation(); | ||
| } | ||
|
|
||
| private void deleteVersionedFiles(File root) { | ||
| if (root.isFile()) { | ||
| String key = informPath.toAbsolutePath() | ||
| .relativize(Paths.get(root.getAbsolutePath())) | ||
| .toString(); | ||
|
|
||
| //System.out.println("key: " + key); | ||
|
|
||
| if (inform.allFiles.containsKey(key)) { | ||
| System.out.println("deleting " + root.getName()); | ||
| root.delete(); | ||
| } | ||
| return; | ||
| } | ||
| if (root.isDirectory()) { | ||
| for (File f : root.listFiles()) { | ||
| if (f.getName().equals(infoFileName) || f.getName().equals(storageFolder)) { | ||
| continue; | ||
| } | ||
| deleteVersionedFiles(f); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private int getIndexOfLessEq(ArrayList<Integer> list, int val) { | ||
| int curr = 0; | ||
| int prev = -1; | ||
| while (curr < list.size() && list.get(curr) <= val) { | ||
| prev = curr; | ||
| curr++; | ||
| } | ||
|
|
||
| return prev; | ||
| } | ||
|
|
||
| private void restoreVersionedFiles(int revision) throws IOException { | ||
| for (Map.Entry<String, ArrayList<Integer>> ent : inform.allFiles.entrySet()) { | ||
| int revisionIdx = getIndexOfLessEq(ent.getValue(), revision); | ||
| if (revisionIdx >= 0) { | ||
| int revNumber = ent.getValue().get(revisionIdx); | ||
| Files.copy(informPath.resolve(storageFolder).resolve(ent.getKey() + revNumber), | ||
| informPath.resolve(ent.getKey())); | ||
| System.out.println("restored " + ent.getKey()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void makeCheckout(int revision) throws IOException, UnversionedException { | ||
| findRepInformation(); | ||
| deleteVersionedFiles(informPath.toAbsolutePath().toFile()); | ||
| restoreVersionedFiles(revision); | ||
| } | ||
|
|
||
| void makeReset(int revision) throws JsonParseException, JsonMappingException, IOException, UnversionedException { | ||
| findRepInformation(); | ||
| Iterator<Entry<String, ArrayList<Integer>>> it = inform.allFiles.entrySet().iterator(); | ||
| while(it.hasNext()) { | ||
| Map.Entry<String, ArrayList<Integer>> ent = it.next(); | ||
| int revisionIndex = getIndexOfLessEq(ent.getValue(), revision); | ||
| if (revisionIndex == -1) { | ||
| it.remove(); | ||
| } else { | ||
| ent.getValue().subList(revisionIndex + 1, ent.getValue().size()).clear(); | ||
| } | ||
|
|
||
| } | ||
| inform.revision = revision; | ||
| inform.commitMessages.subList(revision , inform.commitMessages.size()).clear(); | ||
| inform.timestamps.subList(revision, inform.timestamps.size()).clear(); | ||
| updateRepInformation(); | ||
| } | ||
|
|
||
| String getLog(int revision) throws JsonParseException, JsonMappingException, IOException, UnversionedException { | ||
| findRepInformation(); | ||
| if (revision == -1) { | ||
| revision = inform.revision; | ||
| } | ||
| if(revision == 0) { | ||
| return "Empty log"; | ||
| } | ||
| return "revision: " + revision + "\n" | ||
| + inform.commitMessages.get(revision - 1) + "\n" | ||
| + inform.timestamps.get(revision - 1); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. лог должен выводить список ревизий с указанной |
||
| } | ||
|
|
||
| int getCurrentRevision() { | ||
| return inform.revision; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package hw_git; | ||
|
|
||
| import java.sql.Timestamp; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.TreeMap; | ||
|
|
||
| public class RepInformation { | ||
| int revision = 0; | ||
| ArrayList<String> commitMessages = new ArrayList<>(); | ||
| ArrayList<Timestamp> timestamps = new ArrayList<>(); | ||
| Map<String, ArrayList<Integer>> allFiles = new TreeMap<>(); | ||
|
|
||
| public int getRevision() { | ||
| return revision; | ||
| } | ||
| public void setRevision(int revision) { | ||
| this.revision = revision; | ||
| } | ||
| public List<String> getCommitMessages() { | ||
| return commitMessages; | ||
| } | ||
| public void setCommitMessages(ArrayList<String> commitMessages) { | ||
| this.commitMessages = commitMessages; | ||
| } | ||
| public List<Timestamp> getTimestamps() { | ||
| return timestamps; | ||
| } | ||
| public void setTimestamps(ArrayList<Timestamp> timestamps) { | ||
| this.timestamps = timestamps; | ||
| } | ||
| public Map<String, ArrayList<Integer>> getAllFiles() { | ||
| return allFiles; | ||
| } | ||
| public void setAllFiles(Map<String, ArrayList<Integer>> allFiles) { | ||
| this.allFiles = allFiles; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. зачем тут геттеры-сеттеры, если они не используются) надеюсь, в следующих частях класс приведен в порядок
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это чтобы сериализовывалось. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. понял, в таких случаях лучше коммент в коде оставлять хотя еще лучше все-таки использовать их, а сами поля закрыть |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package hw_git; | ||
|
|
||
| public class UnversionedException extends Exception { | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
кишки торчать наружу не должны, тестам следует смотреть на файлы на диске, т.к. это то, с чем работает пользователь