diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/AbstractPushStrategy.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/AbstractPushStrategy.java index ee328139..d2c3ea60 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/AbstractPushStrategy.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/AbstractPushStrategy.java @@ -54,6 +54,18 @@ public AbstractPushStrategy(StringSet extensions, String fileExtension) this.fileExtension = fileExtension; } + /** + * Indicates if this strategy must work without access to source files. No + * attempt should be made to read, write or push source documents for a + * trans-only strategy. + * + * @return true if this strategy only allows interactions with translation files. + */ + public boolean isTransOnly() + { + return false; + } + /** * Scan srcDir to return a list of all source files. * diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/OfflinePoStrategy.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/OfflinePoStrategy.java index b9877e73..3337ff39 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/OfflinePoStrategy.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/OfflinePoStrategy.java @@ -20,7 +20,19 @@ */ package org.zanata.client.commands.push; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.jboss.resteasy.client.ClientResponse; import org.zanata.adapter.po.PoReader2; +import org.zanata.rest.client.ClientUtility; +import org.zanata.rest.client.ISourceDocResource; +import org.zanata.rest.dto.resource.Resource; +import org.zanata.rest.dto.resource.ResourceMeta; /** * Similar to {@link GettextDirStrategy} but uses msgctxt to map text flow id. @@ -29,10 +41,15 @@ */ public class OfflinePoStrategy extends GettextDirStrategy { - private PoReader2 poReader; + private final ISourceDocResource sourceDocResource; + private final PoReader2 poReader; + + private final URI uri; - public OfflinePoStrategy() + public OfflinePoStrategy(ISourceDocResource sourceDocResource, URI uri) { + this.sourceDocResource = sourceDocResource; + this.uri = uri; poReader = new PoReader2(true); } @@ -41,4 +58,47 @@ protected PoReader2 getPoReader() { return poReader; } + + @Override + public boolean isTransOnly() + { + return true; + }; + + /** + * This implementation retrieves document names from the server. + * All parameters are ignored as there is no disk scanning. + */ + @Override + public Set findDocNames(File srcDir, List includes, List excludes, boolean useDefaultExclude, boolean caseSensitive, boolean excludeLocaleFilenames) throws IOException + { + ClientResponse> getResponse = sourceDocResource.get(null); + ClientUtility.checkResult(getResponse, uri); + List remoteDocList = getResponse.getEntity(); + Set localDocNames = new HashSet(); + for (ResourceMeta doc : remoteDocList) + { + localDocNames.add(doc.getName()); + } + return localDocNames; + } + + @Override + public String[] getSrcFiles(File srcDir, List includes, List excludes, boolean excludeLocaleFilenames, boolean useDefaultExclude, boolean isCaseSensitive) + { + throw new RuntimeException("Source files should never be accessed in a trans-only strategy"); + } + + @Override + public String[] getSrcFiles(File srcDir, List includes, List excludes, List fileExtensions, boolean useDefaultExcludes, boolean isCaseSensitive) + { + throw new RuntimeException("Source files should never be accessed in a trans-only strategy"); + } + + @Override + public Resource loadSrcDoc(File sourceDir, String docName) throws IOException + { + throw new RuntimeException("Source files should never be accessed in a trans-only strategy"); + } + } diff --git a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java index a70f6d59..59ff5d3a 100644 --- a/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java +++ b/zanata-client-commands/src/main/java/org/zanata/client/commands/push/PushCommand.java @@ -71,7 +71,8 @@ public static interface TranslationResourcesVisitor strategies.put(PROJECT_TYPE_PUBLICAN, new GettextDirStrategy()); strategies.put(PROJECT_TYPE_XLIFF, new XliffStrategy()); strategies.put(PROJECT_TYPE_XML, new XmlStrategy()); - strategies.put(PROJECT_TYPE_OFFLINE_PO, new OfflinePoStrategy()); + strategies.put(PROJECT_TYPE_OFFLINE_PO, new OfflinePoStrategy( + getRequestFactory().getSourceDocResource(getOpts().getProj(), getOpts().getProjectVersion()), uri)); } public PushCommand(PushOptions opts) @@ -266,9 +267,10 @@ protected List getObsoleteDocNamesForProjectIterationFromServer() private void pushCurrentModule() throws IOException, RuntimeException { + AbstractPushStrategy strat = getStrategy(getOpts().getProjectType()); File sourceDir = getOpts().getSrcDir(); - if (!sourceDir.exists()) + if (!sourceDir.exists() && !strat.isTransOnly()) { if (getOpts().getEnableModules()) { @@ -281,7 +283,6 @@ private void pushCurrentModule() throws IOException, RuntimeException } } - AbstractPushStrategy strat = getStrategy(getOpts().getProjectType()); final StringSet extensions = strat.getExtensions(); // to save memory, we don't load all the docs into a HashMap @@ -326,7 +327,7 @@ private void pushCurrentModule() throws IOException, RuntimeException } List obsoleteDocs = Collections.emptyList(); - if (pushSource()) + if (pushSource() && !strat.isTransOnly()) { obsoleteDocs = getObsoleteDocsInModuleFromServer(localDocNames); } @@ -348,41 +349,80 @@ private void pushCurrentModule() throws IOException, RuntimeException log.info("Obsolete docs: {}", obsoleteDocs); } + if (pushTrans() && getOpts().getLocaleMapList() == null) + { + throw new ConfigException("pushType set to '" + getOpts().getPushType() + "', but zanata.xml contains no "); + } + if (pushTrans()) { - if (getOpts().getLocaleMapList() == null) - throw new ConfigException("pushType set to '" + getOpts().getPushType() + "', but zanata.xml contains no "); log.warn("pushType set to '" + getOpts().getPushType() + "': existing translations on server may be overwritten/deleted"); + } - if (getOpts().getPushType() == PushPullType.Both) - { - confirmWithUser("This will overwrite existing documents AND TRANSLATIONS on the server, and delete obsolete documents.\n"); - } - else if (getOpts().getPushType() == PushPullType.Trans) + if (strat.isTransOnly()) + { + switch (getOpts().getPushType()) { - confirmWithUser("This will overwrite existing TRANSLATIONS on the server.\n"); + case Source: + { + log.error("You are trying to push source only, but source is not available for this project type.\n"); + log.info("Nothing to do. Aborting\n"); + return; + } + case Both: + { + log.warn("Source is not available for this project type. Source will not be pushed.\n"); + // continue + } + case Trans: + { + confirmWithUser("This will overwrite existing TRANSLATIONS on the server.\n"); + } } } else { - confirmWithUser("This will overwrite existing source documents on the server, and delete obsolete documents.\n"); + if (pushTrans()) + { + if (getOpts().getPushType() == PushPullType.Both) + { + confirmWithUser("This will overwrite existing documents AND TRANSLATIONS on the server, and delete obsolete documents.\n"); + } + else if (getOpts().getPushType() == PushPullType.Trans) + { + confirmWithUser("This will overwrite existing TRANSLATIONS on the server.\n"); + } + } + else + { + confirmWithUser("This will overwrite existing source documents on the server, and delete obsolete documents.\n"); + } } - for (String localDocName : docsToPush) + for (final String localDocName : docsToPush) { try { - final Resource srcDoc = strat.loadSrcDoc(sourceDir, localDocName); - String qualifiedDocName = qualifiedDocName(localDocName); + final String qualifiedDocName = qualifiedDocName(localDocName); final String docUri = RestUtil.convertToDocumentURIId(qualifiedDocName); - srcDoc.setName(qualifiedDocName); - debug(srcDoc); - - if (pushSource()) + final Resource srcDoc; + if (strat.isTransOnly()) + { + srcDoc = null; + } + else { - pushSrcDocToServer(docUri, srcDoc, extensions); + srcDoc = strat.loadSrcDoc(sourceDir, localDocName); + srcDoc.setName(qualifiedDocName); + debug(srcDoc); + + if (pushSource()) + { + pushSrcDocToServer(docUri, srcDoc, extensions); + } } + if (pushTrans()) { strat.visitTranslationResources(localDocName, srcDoc, new TranslationResourcesVisitor() @@ -392,7 +432,7 @@ public void visit(LocaleMapping locale, TranslationsResource targetDoc) { debug(targetDoc); - pushTargetDocToServer(docUri, locale, srcDoc, targetDoc, extensions); + pushTargetDocToServer(docUri, locale, qualifiedDocName, targetDoc, extensions); } }); } @@ -587,11 +627,11 @@ public List splitIntoBatch(TranslationsResource doc, int m return targetDocList; } - private void pushTargetDocToServer(final String docUri, LocaleMapping locale, final Resource srcDoc, TranslationsResource targetDoc, final StringSet extensions) + private void pushTargetDocToServer(final String docUri, LocaleMapping locale, final String localDocName, TranslationsResource targetDoc, final StringSet extensions) { if (!getOpts().isDryRun()) { - log.info("Pushing target doc [name={} size={} client-locale={}] to server [locale={}]", new Object[] { srcDoc.getName(), targetDoc.getTextFlowTargets().size(), locale.getLocalLocale(), locale.getLocale() }); + log.info("Pushing target doc [name={} size={} client-locale={}] to server [locale={}]", new Object[] { localDocName, targetDoc.getTextFlowTargets().size(), locale.getLocalLocale(), locale.getLocale() }); ConsoleUtils.startProgressFeedback(); @@ -647,7 +687,7 @@ private void pushTargetDocToServer(final String docUri, LocaleMapping locale, fi } else { - log.info("pushing target doc [name={} size={} client-locale={}] to server [locale={}] (skipped due to dry run)", srcDoc.getName(), targetDoc.getTextFlowTargets().size(), locale.getLocalLocale(), locale.getLocale()); + log.info("pushing target doc [name={} size={} client-locale={}] to server [locale={}] (skipped due to dry run)", localDocName, targetDoc.getTextFlowTargets().size(), locale.getLocalLocale(), locale.getLocale()); } }