package co.codewizards.cloudstore.client;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import co.codewizards.cloudstore.core.oio.File;
import co.codewizards.cloudstore.core.progress.LoggerProgressMonitor;
import co.codewizards.cloudstore.core.repo.local.LocalRepoManager;
import co.codewizards.cloudstore.core.repo.local.LocalRepoManagerFactory;
import co.codewizards.cloudstore.core.repo.local.LocalRepoRegistryImpl;
import co.codewizards.cloudstore.core.repo.sync.RepoToRepoSync;
public class SyncSubCommand extends SubCommandWithExistingLocalRepo {
private static final Logger logger = LoggerFactory.getLogger(SyncSubCommand.class);
@Argument(metaVar="<remote>", index=1, required=false, usage="An ID or URL of a remote repository. If none is specified, all remote repositories are synced.")
private String remote;
private UUID remoteRepositoryId;
private URL remoteRoot;
@Option(name="-localOnly", required=false, usage="Synchronise locally only. Do not communicate with any remote repository.")
private boolean localOnly;
@Override
public String getSubCommandDescription() {
return "Synchronise a local repository. Depending on the parameters, it synchronises only locally or with one or more remote repositories.";
}
@Override
public void prepare() throws Exception {
super.prepare();
remoteRepositoryId = null;
remoteRoot = null;
if (remote != null && !remote.isEmpty()) {
try {
remoteRepositoryId = UUID.fromString(remote);
} catch (final IllegalArgumentException x) {
try {
remoteRoot = new URL(remote);
} catch (final MalformedURLException y) {
throw new IllegalArgumentException(String.format("<remote> '%s' is neither a valid repositoryId nor a valid URL!", remote));
}
}
}
}
@Override
protected void assertLocalRootNotNull() {
if (!isAll())
super.assertLocalRootNotNull();
}
@Override
public void run() throws Exception {
if (isAll()) {
for (final UUID repositoryId : LocalRepoRegistryImpl.getInstance().getRepositoryIds())
sync(repositoryId);
}
else
sync(localRoot);
}
private void sync(final UUID repositoryId) {
final File localRoot = LocalRepoRegistryImpl.getInstance().getLocalRootOrFail(repositoryId);
sync(localRoot);
}
private void sync(File localRoot) {
final List<URL> remoteRoots = new ArrayList<URL>();
final Map<UUID, URL> filteredRemoteRepositoryId2RemoteRoot = new HashMap<UUID, URL>();
UUID repositoryId;
final LocalRepoManager localRepoManager = LocalRepoManagerFactory.Helper.getInstance().createLocalRepoManagerForExistingRepository(localRoot);
try {
if (localOnly) {
localRepoManager.localSync(new LoggerProgressMonitor(logger));
return;
}
repositoryId = localRepoManager.getRepositoryId();
localRoot = localRepoManager.getLocalRoot();
for (final Map.Entry<UUID, URL> me : localRepoManager.getRemoteRepositoryId2RemoteRootMap().entrySet()) {
final UUID id = me.getKey();
final URL url = me.getValue();
remoteRoots.add(url);
if ((remoteRepositoryId == null && remoteRoot == null)
|| (remoteRepositoryId != null && remoteRepositoryId.equals(id))
|| (remoteRoot != null && remoteRoot.equals(url)))
filteredRemoteRepositoryId2RemoteRoot.put(id, url);
}
} finally {
localRepoManager.close();
}
if (remoteRoots.isEmpty())
System.err.println(String.format("WARNING: The repository %s ('%s') is not connected to any remote repository as client!", repositoryId, localRoot));
else if (filteredRemoteRepositoryId2RemoteRoot.isEmpty())
System.err.println(String.format("WARNING: The repository %s ('%s') is not connected to the specified remote repository ('%s')!", repositoryId, localRoot, remote));
else {
for (final Map.Entry<UUID, URL> me : filteredRemoteRepositoryId2RemoteRoot.entrySet()) {
final UUID remoteRepositoryId = me.getKey();
final URL remoteRoot = me.getValue();
System.out.println("********************************************************************************");
System.out.println(String.format("Syncing %s ('%s') with %s ('%s').", repositoryId, localRoot, remoteRepositoryId, remoteRoot));
System.out.println("********************************************************************************");
final RepoToRepoSync repoToRepoSync = RepoToRepoSync.create(localRoot, remoteRoot);
try {
repoToRepoSync.sync(new LoggerProgressMonitor(logger));
} finally {
repoToRepoSync.close();
}
}
}
}
private boolean isAll() {
return "ALL".equals(local);
}
}