|
|
@@ -1,393 +0,0 @@
|
|
|
-package info.knacki.pass.git.entities;
|
|
|
-
|
|
|
-import android.support.annotation.NonNull;
|
|
|
-
|
|
|
-import java.io.ByteArrayOutputStream;
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileInputStream;
|
|
|
-import java.io.FileNotFoundException;
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.ArrayDeque;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.SortedSet;
|
|
|
-import java.util.TreeSet;
|
|
|
-import java.util.logging.Logger;
|
|
|
-
|
|
|
-import info.knacki.pass.git.GitSha1;
|
|
|
-import info.knacki.pass.io.CharsetHelper;
|
|
|
-import info.knacki.pass.io.FileUtils;
|
|
|
-
|
|
|
-public abstract class GitObject implements Comparable<GitObject>, GitPackable {
|
|
|
- GitTree fParent;
|
|
|
- final byte[] fMode;
|
|
|
- final String fName;
|
|
|
- byte[] fSha1;
|
|
|
-
|
|
|
- @Override
|
|
|
- public int compareTo(@NonNull GitObject gitObject) {
|
|
|
- return fName.toLowerCase().compareTo(gitObject.fName.toLowerCase());
|
|
|
- }
|
|
|
-
|
|
|
- public static class GitBlob extends GitObject {
|
|
|
- private File fFile;
|
|
|
-
|
|
|
- private GitBlob(GitTree parent, byte[] mode, String name, byte[] sha1) {
|
|
|
- super(parent, mode, name, sha1);
|
|
|
- fFile = null;
|
|
|
- }
|
|
|
-
|
|
|
- private GitBlob(GitTree parent, GitBlob copy) {
|
|
|
- this(parent, copy.fMode, copy.fName, copy.fSha1);
|
|
|
- }
|
|
|
-
|
|
|
- GitBlob(GitTree parent, String filename, File f) {
|
|
|
- this(parent, new byte[] { 49, 48, 48, 54, 52, 52 }, filename, GitSha1.getRawSha1OfFile(f));
|
|
|
- fFile = f;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public eType GetPackableType() {
|
|
|
- return eType.eType_Blob;
|
|
|
- }
|
|
|
-
|
|
|
- public static byte[] GetFilePack(File f) throws IOException {
|
|
|
- return FileUtils.ReadAllStream(new FileInputStream(f));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public byte[] GetPack() {
|
|
|
- try
|
|
|
- {
|
|
|
- return GetFilePack(fFile);
|
|
|
- }
|
|
|
- catch (FileNotFoundException e) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- catch(IOException t) {
|
|
|
- t.printStackTrace();
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static class GitRawData extends GitBlob {
|
|
|
- private final byte[] fData;
|
|
|
-
|
|
|
- GitRawData(byte[] sha1, byte[] data) {
|
|
|
- super(null, new byte[] { 49, 48, 48, 54, 52, 52 }, "", sha1);
|
|
|
- fData = data;
|
|
|
- }
|
|
|
-
|
|
|
- public GitRawData(GitTree parent, byte[] mode, String name, byte[] sha1) {
|
|
|
- super(parent, mode, name, sha1);
|
|
|
- fData = null;
|
|
|
- }
|
|
|
-
|
|
|
- public GitRawData(GitTree parent, GitBlob emptyBlob, GitRawData prev) {
|
|
|
- super(parent, new byte[] { 49, 48, 48, 54, 52, 52 }, emptyBlob.GetFilename(), prev.GetHash());
|
|
|
- fData = prev.fData;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public eType GetPackableType() {
|
|
|
- return eType.eType_Blob;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public byte[] GetPack() {
|
|
|
- return GetData();
|
|
|
- }
|
|
|
-
|
|
|
- public byte[] GetData() { return fData; }
|
|
|
- }
|
|
|
-
|
|
|
- public static class GitTree extends GitObject {
|
|
|
- HashMap<String, GitObject> fItems = null;
|
|
|
- ArrayDeque<String> fItemOrder;
|
|
|
-
|
|
|
- private GitTree(GitTree parent, byte[] mode, String name, byte[] sha1) {
|
|
|
- super(parent, mode, name, sha1);
|
|
|
- }
|
|
|
-
|
|
|
- GitTree(GitTree parent, GitTree copy) {
|
|
|
- this(parent, copy.fMode, copy.fName, copy.fSha1);
|
|
|
- Initialize();
|
|
|
- for (Map.Entry<String, GitObject> o: copy.fItems.entrySet()) {
|
|
|
- GitObject src = o.getValue();
|
|
|
- GitObject oCopy = src instanceof GitTree ? new GitTree(this, (GitTree) src) : new GitBlob(this, (GitBlob) src);
|
|
|
- fItems.put(o.getKey(), oCopy);
|
|
|
- }
|
|
|
- for (String i: copy.fItemOrder)
|
|
|
- fItemOrder.push(i);
|
|
|
- }
|
|
|
-
|
|
|
- GitTree(byte[] sha1) {
|
|
|
- super(null, new byte[] { '4', '0', '0', '0', '0' }, "", sha1);
|
|
|
- }
|
|
|
-
|
|
|
- private GitTree(GitTree parent, String filename) {
|
|
|
- super(parent, new byte[] { '4', '0', '0', '0', '0' }, filename, null);
|
|
|
- }
|
|
|
-
|
|
|
- public GitTree(GitTree parent, GitTree content, String filename) {
|
|
|
- this(parent, filename);
|
|
|
- fItems = content.fItems;
|
|
|
- fItemOrder = content.fItemOrder;
|
|
|
- for (GitObject i: fItems.values()) {
|
|
|
- i.SetParent(this);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static GitTree CreateEmpty() {
|
|
|
- GitTree tree = new GitTree(null);
|
|
|
- return tree.Initialize();
|
|
|
- }
|
|
|
-
|
|
|
- public GitTree Initialize() {
|
|
|
- fItems = new HashMap<>();
|
|
|
- fItemOrder = new ArrayDeque<>();
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- boolean IsInitialized() {
|
|
|
- return null != fItems;
|
|
|
- }
|
|
|
-
|
|
|
- public GitObject GetObject(String name) {
|
|
|
- return fItems.get(name);
|
|
|
- }
|
|
|
-
|
|
|
- public GitObject GetObjectFullPath(String path) {
|
|
|
- if ('/' == path.charAt(0))
|
|
|
- path = path.substring(1);
|
|
|
- final int nextSlash = path.indexOf('/');
|
|
|
- final String filename = nextSlash == -1 ? path : (path.substring(0, nextSlash));
|
|
|
- final GitObject obj = GetObject(filename);
|
|
|
- if (obj == null || (obj instanceof GitBlob && nextSlash != -1))
|
|
|
- return null;
|
|
|
- if (nextSlash == -1)
|
|
|
- return obj;
|
|
|
- return ((GitTree) obj).GetObjectFullPath(path.substring(nextSlash +1));
|
|
|
- }
|
|
|
-
|
|
|
- public GitTree AddItem(GitObject item) {
|
|
|
- fItems.put(item.fName, item);
|
|
|
- fItemOrder.push(item.fName);
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- public GitTree FindNextNotInitializedTree() {
|
|
|
- if (!IsInitialized())
|
|
|
- return this;
|
|
|
- for (GitObject obj: fItems.values()) {
|
|
|
- if (!(obj instanceof GitTree))
|
|
|
- continue;
|
|
|
- GitTree child = ((GitTree) obj).FindNextNotInitializedTree();
|
|
|
- if (child != null)
|
|
|
- return child;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- public Iterable<GitObject> GetObjects() {
|
|
|
- ArrayDeque<GitObject> objects = new ArrayDeque<>();
|
|
|
- for (String i: fItemOrder)
|
|
|
- objects.push(fItems.get(i));
|
|
|
- return objects;
|
|
|
- }
|
|
|
-
|
|
|
- public Iterable<GitBlob> GetBlobs() {
|
|
|
- SortedSet<GitBlob> objects = new TreeSet<>();
|
|
|
- for (GitObject i: fItems.values())
|
|
|
- if (i instanceof GitBlob)
|
|
|
- objects.add((GitBlob) i);
|
|
|
- return objects;
|
|
|
- }
|
|
|
-
|
|
|
- public Iterable<GitTree> GetTrees() {
|
|
|
- SortedSet<GitTree> objects = new TreeSet<>();
|
|
|
- for (GitObject i: fItems.values())
|
|
|
- if (i instanceof GitTree)
|
|
|
- objects.add((GitTree) i);
|
|
|
- return objects;
|
|
|
- }
|
|
|
-
|
|
|
- public String GetPath() {
|
|
|
- if (fParent != null)
|
|
|
- return fParent.GetPath() +GetFilename() +"/";
|
|
|
- return GetFilename() +"/";
|
|
|
- }
|
|
|
-
|
|
|
- public void SetRealObject(String key, GitObject obj) {
|
|
|
- if (fItems.containsKey(key)) {
|
|
|
- fItems.put(key, obj);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void FindAllBlobs(HashMap<String, GitBlob> data) {
|
|
|
- String rootPath = GetPath();
|
|
|
- for (GitBlob i: GetBlobs())
|
|
|
- data.put(rootPath +i.GetFilename(), i);
|
|
|
- for (GitTree i: GetTrees())
|
|
|
- i.FindAllBlobs(data);
|
|
|
- }
|
|
|
-
|
|
|
- public HashMap<String, GitBlob> FindAllBlobs() {
|
|
|
- HashMap<String, GitBlob> result = new HashMap<>();
|
|
|
- FindAllBlobs(result);
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean IsRoot() {
|
|
|
- return fParent == null;
|
|
|
- }
|
|
|
-
|
|
|
- public GitObject AddItem(String path, File f) {
|
|
|
- if ('/' == path.charAt(0))
|
|
|
- path = path.substring(1);
|
|
|
- final int nextSlash = path.indexOf('/');
|
|
|
- final String filename = nextSlash == -1 ? path : (path.substring(0, nextSlash));
|
|
|
- final GitObject obj = GetObject(filename);
|
|
|
- final GitObject newItem;
|
|
|
-
|
|
|
- if (obj == null) {
|
|
|
- if (nextSlash != -1) {
|
|
|
- GitTree child = new GitTree(this, filename).Initialize();
|
|
|
- newItem = child.AddItem(path.substring(nextSlash + 1), f);
|
|
|
- fItems.put(filename, child);
|
|
|
- } else {
|
|
|
- newItem = new GitBlob(this, filename, f);
|
|
|
- fItems.put(filename, newItem);
|
|
|
- }
|
|
|
- fItemOrder.push(filename);
|
|
|
- } else if (nextSlash == -1) {
|
|
|
- Remove(filename);
|
|
|
- newItem = new GitBlob(this, filename, f);
|
|
|
- fItems.put(filename, newItem);
|
|
|
- fItemOrder.push(filename);
|
|
|
- } else {
|
|
|
- newItem = ((GitTree) obj).AddItem(path.substring(nextSlash + 1), f);
|
|
|
- }
|
|
|
- fSha1 = null;
|
|
|
- return newItem;
|
|
|
- }
|
|
|
-
|
|
|
- public GitTree Remove(String filename) {
|
|
|
- fItems.remove(filename);
|
|
|
- fItemOrder.remove(filename);
|
|
|
- fSha1 = null;
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- public void Fill(byte[] data) {
|
|
|
- int i = 0;
|
|
|
-
|
|
|
- while (i < data.length) {
|
|
|
- byte[] mode = null;
|
|
|
- int len;
|
|
|
- for (len =0; i +len <data.length && len < 8; ++len) {
|
|
|
- if (data[i + len] == ' ') {
|
|
|
- mode = new byte[len];
|
|
|
- System.arraycopy(data, i, mode, 0, len);
|
|
|
- i += len + 1;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (mode == null)
|
|
|
- break;
|
|
|
- len =0;
|
|
|
- while (i +len < data.length && data[i +len] != 0)
|
|
|
- ++len;
|
|
|
- byte[] filenameBytes = new byte[len];
|
|
|
- System.arraycopy(data, i, filenameBytes, 0, len);
|
|
|
- i += len +1;
|
|
|
- if (i +20 > data.length)
|
|
|
- break;
|
|
|
- byte []sha1 = new byte[20];
|
|
|
- System.arraycopy(data, i, sha1, 0, 20);
|
|
|
- i += 20;
|
|
|
- AddItem(GitObject.factory(this, mode, CharsetHelper.ByteArrayToString(filenameBytes), sha1));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public eType GetPackableType() {
|
|
|
- return eType.eType_Tree;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public byte[] GetPack() {
|
|
|
- try {
|
|
|
- ByteArrayOutputStream str = new ByteArrayOutputStream();
|
|
|
-
|
|
|
- for (GitObject go : GetObjects()) {
|
|
|
- str.write((go.GetMode() + ' ').getBytes());
|
|
|
- if (go.fName.equals("Aa") || "Oo".equals(go.fName))
|
|
|
- Logger.getLogger(GitObject.class.getName()).severe("out file in tree " +go.GetGitPath() +"$" + GitSha1.BytesToString(go.GetHash()));
|
|
|
- str.write(go.GetFilename().getBytes());
|
|
|
- str.write(new byte[]{0});
|
|
|
- str.write(go.GetHash());
|
|
|
- }
|
|
|
- return str.toByteArray();
|
|
|
- }
|
|
|
- catch (IOException e) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public byte[] GetHash() {
|
|
|
- if (null != fSha1)
|
|
|
- return fSha1;
|
|
|
- return fSha1 = GitSha1.getRawSha1OfPackable(this);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private GitObject(GitTree parent, byte[] mode, String name, byte[] sha1) {
|
|
|
- fParent = parent;
|
|
|
- fMode = mode;
|
|
|
- fName = name;
|
|
|
- fSha1 = sha1;
|
|
|
- }
|
|
|
-
|
|
|
- public static GitObject factory(GitTree parent, byte[] mode, String name, byte[] sha1) {
|
|
|
- if (mode[0] == '4') {
|
|
|
- return new GitTree(parent, mode, name, sha1);
|
|
|
- }
|
|
|
- return new GitRawData(parent, mode, name, sha1);
|
|
|
- }
|
|
|
-
|
|
|
- public byte[] GetHash() {
|
|
|
- return fSha1;
|
|
|
- }
|
|
|
-
|
|
|
- public String GetFilename() {
|
|
|
- return fName;
|
|
|
- }
|
|
|
-
|
|
|
- public String GetGitPath() {
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- GitTree parent = fParent;
|
|
|
- sb.insert(0, fName);
|
|
|
- while (parent != null) {
|
|
|
- sb.insert(0, parent.fName + "/");
|
|
|
- parent = parent.fParent;
|
|
|
- }
|
|
|
- return sb.toString();
|
|
|
- }
|
|
|
-
|
|
|
- public GitTree GetParent() {
|
|
|
- return fParent;
|
|
|
- }
|
|
|
-
|
|
|
- private void SetParent(GitTree t) { fParent = t; }
|
|
|
-
|
|
|
- public String GetMode() {
|
|
|
- return new String(fMode);
|
|
|
- }
|
|
|
-
|
|
|
- public int GetDepth() {
|
|
|
- return fParent == null ? 1 : fParent.GetDepth() +1;
|
|
|
- }
|
|
|
-}
|