Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
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"

```
64 changes: 64 additions & 0 deletions hw_git_1/pom.xml
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>
46 changes: 46 additions & 0 deletions hw_git_1/src/main/java/hw_git/GitCli.java
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");
}
}
}
197 changes: 197 additions & 0 deletions hw_git_1/src/main/java/hw_git/GitCore.java
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 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

кишки торчать наружу не должны, тестам следует смотреть на файлы на диске, т.к. это то, с чем работает пользователь

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() {

Choose a reason for hiding this comment

The 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) {

Choose a reason for hiding this comment

The 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);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лог должен выводить список ревизий с указанной

}

int getCurrentRevision() {
return inform.revision;
}
}
39 changes: 39 additions & 0 deletions hw_git_1/src/main/java/hw_git/RepInformation.java
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;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

зачем тут геттеры-сеттеры, если они не используются) надеюсь, в следующих частях класс приведен в порядок

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это чтобы сериализовывалось.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

понял, в таких случаях лучше коммент в коде оставлять

хотя еще лучше все-таки использовать их, а сами поля закрыть

}
5 changes: 5 additions & 0 deletions hw_git_1/src/main/java/hw_git/UnversionedException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package hw_git;

public class UnversionedException extends Exception {

}
Loading