Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@
import com.box.l10n.mojito.cli.filefinder.file.FileType;
import com.box.l10n.mojito.cli.filefinder.file.XcodeXliffFileType;
import com.box.l10n.mojito.rest.client.PollableTaskClient;
import com.box.l10n.mojito.rest.client.RepoTypeClient;
import com.box.l10n.mojito.rest.client.RepositoryClient;
import com.box.l10n.mojito.rest.client.exception.PollableTaskException;
import com.box.l10n.mojito.rest.client.exception.RestClientException;
import com.box.l10n.mojito.rest.entity.Locale;
import com.box.l10n.mojito.rest.entity.PollableTask;
import com.box.l10n.mojito.rest.entity.RepoType;
import com.box.l10n.mojito.rest.entity.Repository;
import com.box.l10n.mojito.rest.entity.RepositoryLocale;
import com.google.common.base.Preconditions;
Expand Down Expand Up @@ -46,11 +48,15 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BOMInputStream;
import org.apache.commons.lang3.StringUtils;
import org.fusesource.jansi.Ansi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;

/**
* @author wyau
Expand All @@ -73,6 +79,8 @@ public class CommandHelper {

@Autowired RepositoryClient repositoryClient;

@Autowired RepoTypeClient repoTypeClient;

@Autowired PollableTaskClient pollableTaskClient;

@Autowired ConsoleWriter consoleWriter;
Expand All @@ -99,6 +107,52 @@ public Repository findRepositoryByName(String repositoryName) throws CommandExce
}
}

/**
* Looks up a repo type by name for update, delete, and view. Rejects a blank name so it is not
* sent as a list-all filter.
*/
public RepoType findRepoTypeByName(String name) throws CommandException {
if (StringUtils.isBlank(name)) {
throw new CommandException("Repo type name is required");
}
List<RepoType> repoTypes = repoTypeClient.getRepoTypes(name.trim());
if (repoTypes.size() != 1) {
throw new CommandException("Repo type with name [" + name + "] is not found");
}
return repoTypes.get(0);
}

/**
* Maps HTTP 400, 404, and 409 to {@link CommandException} using the API response body. Other
* client errors are rethrown so {@code L10nJCommander} handles them.
*
* <p>HTTP 403 is not mapped. {@code AuthenticatedRestTemplate} treats 403 as a stale session
* ({@code FormLoginAuthenticationCsrfTokenInterceptor}): a USER mutate is retried, then thrown as
* {@code RestClientException}, never as {@link HttpClientErrorException}. Same dump as other
* mutating CLI commands (e.g. {@code repo-create}).
*/
public static CommandException repoTypeClientError(HttpClientErrorException ex) {
String fallback = repoTypeClientErrorFallback(ex.getStatusCode());
if (fallback == null) {
throw ex;
}
String body = ex.getResponseBodyAsString();
return new CommandException(!body.isBlank() ? body : fallback, ex);
}

static String repoTypeClientErrorFallback(HttpStatusCode status) {
if (status.equals(HttpStatus.BAD_REQUEST)) {
return "Invalid repo type";
}
if (status.equals(HttpStatus.NOT_FOUND)) {
return "Repo type is not found";
}
if (status.equals(HttpStatus.CONFLICT)) {
return "Repo type already exists";
}
return null;
}

/**
* Get all repositories
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.box.l10n.mojito.cli.command;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.box.l10n.mojito.cli.command.param.Param;
import com.box.l10n.mojito.cli.console.ConsoleWriter;
import com.box.l10n.mojito.rest.client.RepoTypeClient;
import com.box.l10n.mojito.rest.entity.RepoType;
import org.fusesource.jansi.Ansi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;

/** Creates a repo type with a name and optional description. */
@Component
@Scope("prototype")
@Parameters(
commandNames = {"repo-type-create"},
commandDescription = "Creates a repo type")
public class RepoTypeCreateCommand extends Command {

static Logger logger = LoggerFactory.getLogger(RepoTypeCreateCommand.class);

@Autowired ConsoleWriter consoleWriter;

@Autowired RepoTypeClient repoTypeClient;

@Parameter(
names = {Param.REPO_TYPE_NAME_LONG, Param.REPO_TYPE_NAME_SHORT},
arity = 1,
required = true,
description = Param.REPO_TYPE_NAME_DESCRIPTION)
String nameParam;

@Parameter(
names = {Param.REPO_TYPE_DESCRIPTION_LONG, Param.REPO_TYPE_DESCRIPTION_SHORT},
arity = 1,
required = false,
description = Param.REPO_TYPE_DESCRIPTION_DESCRIPTION)
String descriptionParam;

@Override
protected void execute() throws CommandException {
consoleWriter.a("Create repo type: ").fg(Ansi.Color.CYAN).a(nameParam).println();

try {
RepoType toCreate = new RepoType();
toCreate.setName(nameParam);
toCreate.setDescription(descriptionParam);

RepoType created = repoTypeClient.createRepoType(toCreate);
consoleWriter
.newLine()
.a("created --> repo type id: ")
.fg(Ansi.Color.MAGENTA)
.a(created.getId())
.println();
} catch (HttpClientErrorException ex) {
throw CommandHelper.repoTypeClientError(ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.box.l10n.mojito.cli.command;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.box.l10n.mojito.cli.command.param.Param;
import com.box.l10n.mojito.cli.console.ConsoleWriter;
import com.box.l10n.mojito.rest.client.RepoTypeClient;
import com.box.l10n.mojito.rest.entity.RepoType;
import org.fusesource.jansi.Ansi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;

/** Deletes an existing repo type by name. */
@Component
@Scope("prototype")
@Parameters(
commandNames = {"repo-type-delete"},
commandDescription = "Deletes a repo type")
public class RepoTypeDeleteCommand extends Command {

static Logger logger = LoggerFactory.getLogger(RepoTypeDeleteCommand.class);

@Autowired ConsoleWriter consoleWriter;

@Autowired CommandHelper commandHelper;

@Autowired RepoTypeClient repoTypeClient;

@Parameter(
names = {Param.REPO_TYPE_NAME_LONG, Param.REPO_TYPE_NAME_SHORT},
arity = 1,
required = true,
description = Param.REPO_TYPE_NAME_DESCRIPTION)
String nameParam;

@Override
protected void execute() throws CommandException {
consoleWriter.a("Delete repo type: ").fg(Ansi.Color.CYAN).a(nameParam).println();

RepoType existing = commandHelper.findRepoTypeByName(nameParam);
try {
repoTypeClient.deleteRepoType(existing.getId());
} catch (HttpClientErrorException ex) {
throw CommandHelper.repoTypeClientError(ex);
}

consoleWriter
.newLine()
.a("deleted --> repo type name: ")
.fg(Ansi.Color.MAGENTA)
.a(nameParam)
.println();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.box.l10n.mojito.cli.command;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.box.l10n.mojito.cli.command.param.Param;
import com.box.l10n.mojito.cli.console.ConsoleWriter;
import com.box.l10n.mojito.rest.client.RepoTypeClient;
import com.box.l10n.mojito.rest.entity.RepoType;
import org.fusesource.jansi.Ansi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;

/** Updates name and/or description of an existing repo type. */
@Component
@Scope("prototype")
@Parameters(
commandNames = {"repo-type-update"},
commandDescription = "Updates a repo type")
public class RepoTypeUpdateCommand extends Command {

static Logger logger = LoggerFactory.getLogger(RepoTypeUpdateCommand.class);

@Autowired ConsoleWriter consoleWriter;

@Autowired CommandHelper commandHelper;

@Autowired RepoTypeClient repoTypeClient;

@Parameter(
names = {Param.REPO_TYPE_NAME_LONG, Param.REPO_TYPE_NAME_SHORT},
arity = 1,
required = true,
description = Param.REPO_TYPE_NAME_DESCRIPTION)
String nameParam;

@Parameter(
names = {Param.REPO_TYPE_NEW_NAME_LONG, Param.REPO_TYPE_NEW_NAME_SHORT},
arity = 1,
required = false,
description = Param.REPO_TYPE_NEW_NAME_DESCRIPTION)
String newNameParam;

@Parameter(
names = {Param.REPO_TYPE_DESCRIPTION_LONG, Param.REPO_TYPE_DESCRIPTION_SHORT},
arity = 1,
required = false,
description = Param.REPO_TYPE_DESCRIPTION_DESCRIPTION)
String descriptionParam;

@Override
protected void execute() throws CommandException {
consoleWriter.a("Update repo type: ").fg(Ansi.Color.CYAN).a(nameParam).println();

if (newNameParam == null && descriptionParam == null) {
throw new CommandException(
"Must provide at least one of the following options: --new-name, --description");
}

RepoType existing = commandHelper.findRepoTypeByName(nameParam);

try {
RepoType updated =
repoTypeClient.updateRepoType(
existing.getId(), nameAndDescriptionPatch(newNameParam, descriptionParam));
consoleWriter
.newLine()
.a("updated --> repo type id: ")
.fg(Ansi.Color.MAGENTA)
.a(updated.getId())
.println();
} catch (HttpClientErrorException ex) {
throw CommandHelper.repoTypeClientError(ex);
}
}

/**
* PATCH body for name and/or description only. {@code integrityCheckers} is explicitly {@code
* null} so the field is omitted (leave unchanged). Do not set {@code aiPrompt}; it stays {@code
* null} and is omitted. A non-null empty checker set serializes as {@code []} and would clear
* checkers on the server.
*/
static RepoType nameAndDescriptionPatch(String newName, String description) {
RepoType patch = new RepoType();
patch.setName(newName);
patch.setDescription(description);
patch.setIntegrityCheckers(null);
return patch;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.box.l10n.mojito.cli.command;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.box.l10n.mojito.cli.command.param.Param;
import com.box.l10n.mojito.cli.console.ConsoleWriter;
import com.box.l10n.mojito.rest.entity.RepoType;
import org.fusesource.jansi.Ansi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/** Views id, name, and description of an existing repo type. */
@Component
@Scope("prototype")
@Parameters(
commandNames = {"repo-type-view"},
commandDescription = "View a repo type")
public class RepoTypeViewCommand extends Command {

static Logger logger = LoggerFactory.getLogger(RepoTypeViewCommand.class);

@Autowired ConsoleWriter consoleWriter;

@Autowired CommandHelper commandHelper;

@Parameter(
names = {Param.REPO_TYPE_NAME_LONG, Param.REPO_TYPE_NAME_SHORT},
arity = 1,
required = true,
description = Param.REPO_TYPE_NAME_DESCRIPTION)
String nameParam;

@Override
protected void execute() throws CommandException {
consoleWriter.a("View repo type: ").fg(Ansi.Color.CYAN).a(nameParam).println();

RepoType repoType = commandHelper.findRepoTypeByName(nameParam);
String description = repoType.getDescription() != null ? repoType.getDescription() : "";

consoleWriter
.newLine()
.a("Repo type id --> ")
.fg(Ansi.Color.MAGENTA)
.a(repoType.getId())
.println();
consoleWriter.a("Name --> ").fg(Ansi.Color.MAGENTA).a(repoType.getName()).println();
consoleWriter.a("Description --> ").fg(Ansi.Color.MAGENTA).a(description).println();
consoleWriter.println();
}
}
13 changes: 13 additions & 0 deletions cli/src/main/java/com/box/l10n/mojito/cli/command/param/Param.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ public class Param {
public static final String REPOSITORY_DESCRIPTION_DESCRIPTION =
"Description of the repository to create or update";

public static final String REPO_TYPE_NAME_LONG = "--name";
public static final String REPO_TYPE_NAME_SHORT = "-n";
public static final String REPO_TYPE_NAME_DESCRIPTION = "Name of the repo type";

public static final String REPO_TYPE_NEW_NAME_LONG = "--new-name";
public static final String REPO_TYPE_NEW_NAME_SHORT = "-nn";
public static final String REPO_TYPE_NEW_NAME_DESCRIPTION = "New name for the repo type";

public static final String REPO_TYPE_DESCRIPTION_LONG = "--description";
public static final String REPO_TYPE_DESCRIPTION_SHORT = "-d";
public static final String REPO_TYPE_DESCRIPTION_DESCRIPTION =
"Description of the repo type to create or update";

public static final String REPOSITORY_LOCALES_LONG = "--locales";
public static final String REPOSITORY_LOCALES_SHORT = "-l";
public static final String REPOSITORY_LOCALES_DESCRIPTION =
Expand Down
Loading
Loading