package aQute.libg.remote.sink;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import aQute.lib.io.IO;
import aQute.libg.cryptography.SHA1;
import aQute.libg.remote.Delta;
import aQute.libg.remote.Source;
public class SinkFS {
final Map<File,String> shas = new ConcurrentHashMap<File,String>();
final Map<String,File> files = new ConcurrentHashMap<String,File>();
private Source[] sources;
private File shacache;
public SinkFS(Source[] sources, File shacache) {
this.shacache = shacache;
setSources(sources);
}
public void setSources(Source[] sources) {
this.sources = sources;
}
public boolean delta(File cwd, Collection<Delta> deltas) {
for (Delta delta : deltas) {
try {
delta(cwd, delta);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return true;
}
private void delta(File cwd, Delta delta) throws Exception {
File file = new File(delta.path);
if (file.isAbsolute())
throw new IllegalArgumentException("Absolute paths are not allowed " + delta.path);
file = new File(cwd, delta.path);
if (delta.delete)
IO.delete(file);
else {
if (delta.sha != null) {
String existing = shas.get(file);
if (existing == null || !delta.sha.equals(existing)) {
byte[] data = getData(delta.sha);
if (data != null) {
copy(data, file, delta.sha);
} else
shas.remove(file);
}
} else if (delta.content != null) {
byte[] bytes = delta.content.getBytes(UTF_8);
String sha = SHA1.digest(bytes).asHex();
copy(bytes, file, sha);
}
}
}
private void copy(byte[] data, File file, String sha) throws Exception {
IO.mkdirs(file.getParentFile());
IO.copy(data, file);
shas.put(file, sha);
}
private byte[] getData(String sha) throws Exception {
File shaf = new File(shacache, sha);
if (shaf.isFile()) {
return IO.read(shaf);
}
for (Source source : sources) {
byte[] data = source.getData(sha);
if (data != null) {
File tmp = IO.createTempFile(shacache, "shacache", null);
IO.copy(data, tmp);
IO.rename(tmp, shaf);
return data;
}
}
return null;
}
}