package uk.ac.ic.wlgitbridge.data.model;
import com.google.api.client.auth.oauth2.Credential;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
import uk.ac.ic.wlgitbridge.data.SnapshotFetcher;
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
import uk.ac.ic.wlgitbridge.data.model.db.PersistentStore;
import uk.ac.ic.wlgitbridge.data.model.db.SqlitePersistentStore;
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotAttachment;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
import uk.ac.ic.wlgitbridge.util.Log;
import uk.ac.ic.wlgitbridge.util.Util;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* Created by Winston on 06/11/14.
*/
public class DataStore {
private final File rootGitDirectory;
private final PersistentStore persistentStore;
private final SnapshotFetcher snapshotFetcher;
private final ResourceFetcher resourceFetcher;
public DataStore(String rootGitDirectoryPath) {
rootGitDirectory = initRootGitDirectory(rootGitDirectoryPath);
persistentStore = new SqlitePersistentStore(rootGitDirectory);
List<String> excludedFromDeletion = persistentStore.getProjectNames();
excludedFromDeletion.add(".wlgb");
Util.deleteInDirectoryApartFrom(
rootGitDirectory,
excludedFromDeletion.toArray(new String[] {})
);
snapshotFetcher = new SnapshotFetcher();
resourceFetcher = new ResourceFetcher(persistentStore);
}
public void updateProjectWithName(Credential oauth2,
String name,
Repository repository)
throws IOException,
SnapshotPostException,
GitAPIException,
ForbiddenException {
LinkedList<Snapshot> snapshots =
snapshotFetcher.getSnapshotsForProjectAfterVersion(
oauth2,
name,
persistentStore.getLatestVersionForProject(name)
);
makeCommitsFromSnapshots(name, repository, snapshots);
if (!snapshots.isEmpty()) {
persistentStore.setLatestVersionForProject(
name,
snapshots.getLast().getVersionID()
);
}
}
private void makeCommitsFromSnapshots(String name,
Repository repository,
List<Snapshot> snapshots)
throws IOException, GitAPIException, SnapshotPostException {
for (Snapshot snapshot : snapshots) {
Map<String, RawFile> fileTable = new RepositoryObjectTreeWalker(repository).getDirectoryContents().getFileTable();
List<RawFile> files = new LinkedList<RawFile>();
files.addAll(snapshot.getSrcs());
Map<String, byte[]> fetchedUrls = new HashMap<String, byte[]>();
for (SnapshotAttachment snapshotAttachment : snapshot.getAtts()) {
files.add(
resourceFetcher.get(
name,
snapshotAttachment.getUrl(),
snapshotAttachment.getPath(),
fileTable,
fetchedUrls
)
);
}
Log.info(
"[{}] Committing version ID: {}",
name,
snapshot.getVersionID()
);
commit(name,
new GitDirectoryContents(
files,
rootGitDirectory,
name,
snapshot),
repository);
}
}
private void commit(String name,
GitDirectoryContents contents,
Repository repository) throws IOException,
GitAPIException {
Log.info("[{}] Writing commit", name);
contents.write();
Git git = new Git(repository);
Log.info("[{}] Getting missing files", name);
Set<String> missingFiles = git.status().call().getMissing();
for (String missing : missingFiles) {
Log.info("[{}] Git rm {}", name, missing);
git.rm().setCached(true).addFilepattern(missing).call();
}
Log.info("[{}] Calling Git add", name);
git.add().addFilepattern(".").call();
Log.info("[{}] Calling Git commit", name);
git.commit(
).setAuthor(
new PersonIdent(
contents.getUserName(),
contents.getUserEmail(),
contents.getWhen(),
TimeZone.getDefault()
)
).setMessage(
contents.getCommitMessage()
).call();
persistentStore.deleteFilesForProject(
name,
missingFiles.toArray(new String[missingFiles.size()])
);
Log.info(
"[{}] Deleting files in directory: {}",
name,
contents.getDirectory().getAbsolutePath()
);
Util.deleteInDirectoryApartFrom(contents.getDirectory(), ".git");
}
public CandidateSnapshot
createCandidateSnapshot(String projectName,
RawDirectory directoryContents,
RawDirectory oldDirectoryContents)
throws SnapshotPostException,
IOException {
CandidateSnapshot candidateSnapshot = new CandidateSnapshot(
projectName,
persistentStore.getLatestVersionForProject(projectName),
directoryContents,
oldDirectoryContents
);
candidateSnapshot.writeServletFiles(rootGitDirectory);
return candidateSnapshot;
}
public void approveSnapshot(int versionID,
CandidateSnapshot candidateSnapshot) {
List<String> deleted = candidateSnapshot.getDeleted();
persistentStore.setLatestVersionForProject(
candidateSnapshot.getProjectName(),
versionID
);
persistentStore.deleteFilesForProject(
candidateSnapshot.getProjectName(),
deleted.toArray(new String[deleted.size()])
);
}
private File initRootGitDirectory(String rootGitDirectoryPath) {
File rootGitDirectory = new File(rootGitDirectoryPath);
rootGitDirectory.mkdirs();
return rootGitDirectory;
}
}