提交 c816f965 编写于 作者: D Devin Nusbaum 提交者: Oleg Nenashev

[JENKINS-22936] Move rename logic to AbstractItem (#3289)

* Move rename infrastructure to a dedicated page at the AbstractItem level

* Preserve existing translations where applicable

* Keep doDoRename method at Job level and remove unneeded compatibility page

* Fix tests

* Fix Javadoc

* Update existing rename tests to use new page

* Update test names for clarity

* Add since tag for newly introduced APIs

* Apply project naming strategy to all renamed items, not just jobs

* Use shorthand accessor

* Clean up Job#doDoRename and deprecate it

* Use new-style web method for doDoRename2

* Remove CheckForNull tag from void method and update Javadoc

* Change names to doConfirmRename and confirm-rename.jelly

* Rename index.jelly to action.jelly and use j:if tag correctly

* Update permission check and remove unused import

* Use new url and update method name in test

* Fix Javadoc

* Fix URL in JobTest

* Update Javadoc for AbstractItem#isNameEditable
上级 8f512603
......@@ -36,12 +36,14 @@ import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.model.queue.Tasks;
import hudson.model.queue.WorkUnit;
import hudson.security.ACLContext;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.security.ACL;
import hudson.util.AlternativeUiTextProvider;
import hudson.util.AlternativeUiTextProvider.Message;
import hudson.util.AtomicFileWriter;
import hudson.util.FormValidation;
import hudson.util.IOUtils;
import hudson.util.Secret;
import java.util.Iterator;
......@@ -72,12 +74,16 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import org.acegisecurity.AccessDeniedException;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.HttpDeletable;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;
import org.xml.sax.SAXException;
......@@ -228,6 +234,111 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
this.name = name;
}
/**
* Controls whether the default rename action is available for this item.
*
* @return whether {@link #name} can be modified by a user
* @see #checkRename
* @see #renameTo
* @since FIXME
*/
public boolean isNameEditable() {
return false;
}
/**
* Renames this item
*/
@RequirePOST
@Restricted(NoExternalUse.class)
public HttpResponse doConfirmRename(@QueryParameter String newName) throws IOException {
newName = newName == null ? null : newName.trim();
FormValidation validationError = doCheckNewName(newName);
if (validationError.kind != FormValidation.Kind.OK) {
throw new Failure(validationError.getMessage());
}
renameTo(newName);
// send to the new job page
// note we can't use getUrl() because that would pick up old name in the
// Ancestor.getUrl()
return HttpResponses.redirectTo("../" + newName);
}
/**
* Called by {@link #doConfirmRename} and {@code rename.jelly} to validate renames.
* @return {@link FormValidation#ok} if this item can be renamed as specified, otherwise
* {@link FormValidation#error} with a message explaining the problem.
*/
@Restricted(NoExternalUse.class)
public @Nonnull FormValidation doCheckNewName(@QueryParameter String newName) {
// TODO: Create an Item.RENAME permission to use here, see JENKINS-18649.
if (!hasPermission(Item.CONFIGURE)) {
if (parent instanceof AccessControlled) {
((AccessControlled)parent).checkPermission(Item.CREATE);
}
checkPermission(Item.DELETE);
}
newName = newName == null ? null : newName.trim();
try {
Jenkins.checkGoodName(newName);
assert newName != null; // Would have thrown Failure
Jenkins.get().getProjectNamingStrategy().checkName(newName);
checkIfNameIsUsed(newName);
checkRename(newName);
} catch (Failure e) {
return FormValidation.error(e.getMessage());
}
return FormValidation.ok();
}
/**
* Check new name for job
* @param newName - New name for job.
*/
private void checkIfNameIsUsed(@Nonnull String newName) throws Failure {
try {
Item item = getParent().getItem(newName);
if (item != null) {
throw new Failure(Messages.AbstractItem_NewNameInUse(newName));
}
try (ACLContext ctx = ACL.as(ACL.SYSTEM)) {
item = getParent().getItem(newName);
if (item != null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " +
"User {2} has no {3} permission for existing job with the same name",
new Object[] {this.getFullName(), newName, ctx.getPreviousContext().getAuthentication().getName(), Item.DISCOVER.name} );
}
// Don't explicitly mention that there is another item with the same name.
throw new Failure(Messages.Jenkins_NotAllowedName(newName));
}
}
} catch(AccessDeniedException ex) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " +
"User {2} has {3} permission, but no {4} for existing job with the same name",
new Object[] {this.getFullName(), newName, User.current(), Item.DISCOVER.name, Item.READ.name} );
}
throw new Failure(Messages.AbstractItem_NewNameInUse(newName));
}
}
/**
* Allows subclasses to block renames for domain-specific reasons. Generic validation of the new name
* (e.g., null checking, checking for illegal characters, and checking that the name is not in use)
* always happens prior to calling this method.
*
* @param newName the new name for the item
* @throws Failure if the rename should be blocked
* @since FIXME
* @see Job#checkRename
*/
protected void checkRename(@Nonnull String newName) throws Failure {
}
/**
* Renames this item.
* Not all the Items need to support this operation, but if you decide to do so,
......
......@@ -56,7 +56,6 @@ import hudson.util.DescribableList;
import hudson.util.FormApply;
import hudson.util.Graph;
import hudson.util.ProcessTree;
import hudson.util.QuotedStringTokenizer;
import hudson.util.RunList;
import hudson.util.ShiftedCategoryAxis;
import hudson.util.StackedAreaRenderer2;
......@@ -68,7 +67,6 @@ import java.awt.Color;
import java.awt.Paint;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Calendar;
......@@ -122,9 +120,6 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;
/**
* A job is an runnable entity under the monitoring of Hudson.
......@@ -324,6 +319,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
/**
* Returns whether the name of this job can be changed by user.
*/
@Override
public boolean isNameEditable() {
return true;
}
......@@ -1356,39 +1352,17 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
}
ItemListener.fireOnUpdated(this);
String newName = req.getParameter("name");
final ProjectNamingStrategy namingStrategy = Jenkins.getInstance().getProjectNamingStrategy();
if (validRename(name, newName)) {
newName = newName.trim();
// check this error early to avoid HTTP response splitting.
Jenkins.checkGoodName(newName);
namingStrategy.checkName(newName);
if (FormApply.isApply(req)) {
FormApply.applyResponse("notificationBar.show(" + QuotedStringTokenizer.quote(Messages.Job_you_must_use_the_save_button_if_you_wish()) + ",notificationBar.WARNING)").generateResponse(req, rsp, null);
} else {
rsp.sendRedirect("rename?newName=" + URLEncoder.encode(newName, "UTF-8"));
}
} else {
if(namingStrategy.isForceExistingJobs()){
namingStrategy.checkName(name);
}
FormApply.success(".").generateResponse(req, rsp, null);
}
} catch (JSONException e) {
LOGGER.log(Level.WARNING, "failed to parse " + json, e);
sendError(e, req, rsp);
}
}
private boolean validRename(String oldName, String newName) {
if (newName == null) {
return false;
}
boolean noChange = oldName.equals(newName);
boolean spaceAdded = oldName.equals(newName.trim());
return !noChange && !spaceAdded;
}
/**
* Derived class can override this to perform additional config submission
* work.
......@@ -1586,32 +1560,25 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
/**
* Renames this job.
* @deprecated Exists for backwards compatibility, use {@link #doConfirmRename} instead.
*/
@Deprecated
@RequirePOST
public/* not synchronized. see renameTo() */void doDoRename(
StaplerRequest req, StaplerResponse rsp) throws IOException,
ServletException {
if (!hasPermission(CONFIGURE)) {
// rename is essentially delete followed by a create
checkPermission(CREATE);
checkPermission(DELETE);
}
String newName = req.getParameter("newName");
Jenkins.checkGoodName(newName);
doConfirmRename(newName).generateResponse(req, rsp, null);
}
/**
* {@inheritDoc}
*/
@Override
protected void checkRename(String newName) throws Failure {
if (isBuilding()) {
// redirect to page explaining that we can't rename now
rsp.sendRedirect("rename?newName=" + URLEncoder.encode(newName, "UTF-8"));
return;
throw new Failure(Messages.Job_NoRenameWhileBuilding());
}
renameTo(newName);
// send to the new job page
// note we can't use getUrl() because that would pick up old name in the
// Ancestor.getUrl()
rsp.sendRedirect2("../" + newName);
}
public void doRssAll(StaplerRequest req, StaplerResponse rsp)
......@@ -1645,58 +1612,4 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
}
private final static HexStringConfidentialKey SERVER_COOKIE = new HexStringConfidentialKey(Job.class,"serverCookie",16);
/**
* Check new name for job
* @param newName - New name for job
* @return {@code true} - if newName occupied and user has permissions for this job
* {@code false} - if newName occupied and user hasn't permissions for this job
* {@code null} - if newName didn't occupied
*
* @throws Failure if the given name is not good
*/
@CheckForNull
@Restricted(NoExternalUse.class)
public Boolean checkIfNameIsUsed(@Nonnull String newName) throws Failure{
Item item = null;
Jenkins.checkGoodName(newName);
try {
item = getParent().getItem(newName);
} catch(AccessDeniedException ex) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " +
"User {2} has {3} permission, but no {4} for existing job with the same name",
new Object[] {this.getFullName(), newName, User.current().getFullName(), Item.DISCOVER.name, Item.READ.name} );
}
return true;
}
if (item != null) {
// User has Read permissions for existing job with the same name
return true;
} else {
SecurityContext initialContext = null;
try {
initialContext = hudson.security.ACL.impersonate(ACL.SYSTEM);
item = getParent().getItem(newName);
if (item != null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "Unable to rename the job {0}: name {1} is already in use. " +
"User {2} has no {3} permission for existing job with the same name",
new Object[] {this.getFullName(), newName, initialContext.getAuthentication().getName(), Item.DISCOVER.name} );
}
return false;
}
} finally {
if (initialContext != null) {
SecurityContextHolder.setContext(initialContext);
}
}
}
return null;
}
}
/*
* The MIT License
*
* Copyright 2018 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package jenkins.model;
import hudson.Extension;
import hudson.model.AbstractItem;
import hudson.model.Action;
import java.util.Collection;
import java.util.Collections;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
@Restricted(NoExternalUse.class)
public class RenameAction implements Action {
@Override
public String getIconFileName() {
return "notepad.png";
}
@Override
public String getDisplayName() {
return "Rename";
}
@Override
public String getUrlName() {
return "confirm-rename";
}
@Extension
public static class TransientActionFactoryImpl extends TransientActionFactory<AbstractItem> {
@Override
public Class<AbstractItem> type() {
return AbstractItem.class;
}
@Override
public Collection<? extends Action> createFor(AbstractItem target) {
if (target.isNameEditable()) {
return Collections.singleton(new RenameAction());
} else {
return Collections.emptyList();
}
}
}
}
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
Copyright 2018 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......@@ -22,43 +22,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<!-- Rename project -->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<l:layout>
<l:layout title="${%Rename}">
<st:include page="sidepanel.jelly" />
<l:main-panel>
<j:set var="newName" value="${request.getParameter('newName')}" />
<j:set var="checkIfNameIsUsed" value="${it.checkIfNameIsUsed(newName)}" />
<j:choose>
<j:when test="${it.isBuilding()}">
${%noRenameWhileBuilding}
<j:if test="${request.referer.endsWith('/configure')}">
<br/> ${%configWasSaved}
</j:if>
</j:when>
<j:when test="${checkIfNameIsUsed != null and !it.name.equalsIgnoreCase(newName)}" >
<j:if test="${checkIfNameIsUsed}" >
${%newNameInUse(newName)}
</j:if>
<j:if test="${!checkIfNameIsUsed}" >
${%newNameNotValid(newName)}
</j:if>
<j:if test="${request.referer.endsWith('/configure')}">
<br/> ${%configWasSaved}
</j:if>
</j:when>
<j:otherwise>
<form method="post" action="doRename">
${%description(it.name, newName)}
<input type="hidden" name="newName" value="${newName}" />
<f:submit value="${%Yes}" />
</form>
</j:otherwise>
</j:choose>
<h1><l:icon class="icon-notepad icon-xlg"/> ${%DescribeRename(it.pronoun, it.name)}</h1>
<f:form method="post" action="confirmRename" name="config" tableClass="config-table scrollspy">
<f:entry title="${%NewName}">
<f:textbox name="newName" value="${it.name}" autocomplete="on" checkUrl="checkNewName" checkDependsOn="newName"/>
</f:entry>
<f:bottomButtonBar>
<f:submit value="${%Rename}" />
</f:bottomButtonBar>
</f:form>
<st:adjunct includes="lib.form.confirm" />
</l:main-panel>
</l:layout>
</j:jelly>
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc.
# Copyright (c) 2018 CloudBees, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
......@@ -20,6 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
No=Nej
Yes=Ja
description=\u00C4r du s\u00E4ker att du vill \u00E4ndra namn ifr\u00E5n {0} till {1}?
DescribeRename=Rename {0} {1}
NewName=New Name
Rename=Rename
......@@ -44,11 +44,6 @@ THE SOFTWARE.
<j:set var="descriptor" value="${it.descriptor}" />
<j:set var="instance" value="${it}" />
<j:if test="${it.isNameEditable()}">
<f:entry title="${%name(it.pronoun)}">
<f:textbox name="name" value="${it.name}" autocomplete="on"/>
</f:entry>
</j:if>
<f:entry title="${%Description}" help="${app.markupFormatter.helpUrl}">
<f:textarea name="description" value="${it.description}" codemirror-mode="${app.markupFormatter.codeMirrorMode}" codemirror-config="${app.markupFormatter.codeMirrorConfig}" previewEndpoint="/markupFormatter/previewDescription"/>
</f:entry>
......
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
noRenameWhileBuilding=Unable to rename a job while it is building.
newNameInUse=The name {0} is already in use.
newNameNotValid=The name {0} is not valid.
configWasSaved=All other configuration options were saved.
description=Are you sure about renaming {0} to {1}?
Yes=Yes
# The MIT License
#
# Bulgarian translation: Copyright (c) 2015, 2016, Alexander Shopov <ash@kambanaria.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# The name {0} is already in use.
newNameInUse=\
\u0418\u043c\u0435\u0442\u043e \u201e{0}\u201c \u0435 \u0437\u0430\u0435\u0442\u043e.
# Yes
Yes=\
\u0414\u0430
# Unable to rename a job while it is building.
noRenameWhileBuilding=\
\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u043d\u0435\u0439\u043d\u043e\u0442\u043e \u0438\u0437\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0435 .
# All other configuration options were saved.
configWasSaved=\
\u0412\u0441\u0438\u0447\u043a\u0438 \u0434\u0440\u0443\u0433\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0430 \u0437\u0430\u043f\u0430\u0437\u0435\u043d\u0438.
# Are you sure about renaming {0} to {1}?
description=\
\u0421\u0438\u0433\u0443\u0440\u043d\u0438 \u043b\u0438 \u0441\u0442\u0435, \u0447\u0435 \u0438\u0441\u043a\u0430\u0442\u0435 \u0434\u0430 \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0435 \u201e{0}\u201c \u043d\u0430 \u201e{1}\u201c?
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc. Kohsuke Kawaguchi. Knud Poulsen.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
noRenameWhileBuilding=Kan ikke omd\u00f8be et job imens det bygger
Yes=Ja
No=Nej
configWasSaved=Alle andre konfigurationsindstillinger blev gemt.
description=Er du sikker p\u00e5 at du vil omd\u00f8be {0} til {1}?
newNameInUse=Navnet {0} er allerede i brug
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, Simon Wiest
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
description=Möchten Sie wirklich {0} in {1} umbenennen?
Yes=Ja
noRenameWhileBuilding=Ein Job kann nicht umbenannt werden, während er gebaut wird.
configWasSaved=Alle anderen Konfigurationseinstellungen wurden übernommen.
newNameInUse=Der Name {0} wird bereits verwendet.
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
noRenameWhileBuilding=No es posible renombrar un proyecto mientras se está ejecutando.
configWasSaved=Las demás opciones de configuración sí se han guardado.
description=¿Estás seguro de querer renombrar {0} a {1}?
Yes=
No=No
newNameInUse=El nombre {0} ya existe.
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
description=Voulez-vous vraiment renommer {0} en {1}?
Yes=Oui
No=Non
configWasSaved=Tutte le altre opzioni di configurazione sono state salvate.
newNameNotValid=Il nome {0} non è valido.
description=Rinominare {0} in {1}?
noRenameWhileBuilding=Impossibile rinominare un processo finché la sua compilazione è in corso.
newNameInUse=Il nome {0} è già utilizzato.
Yes=
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
noRenameWhileBuilding=\u30d3\u30eb\u30c9\u4e2d\u306b\u30b8\u30e7\u30d6\u540d\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002
newNameInUse=\u30b8\u30e7\u30d6\u540d {0} \u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002
configWasSaved=\u4ed6\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u306f\u3059\u3079\u3066\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002
description={0}\u304b\u3089{1}\u306b\u5909\u66f4\u3057\u3066\u3088\u308d\u3057\u3044\u3067\u3059\u304b?
Yes=\u306f\u3044
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc., Cleiber Silva, Fernando Boaglio
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Unable to rename a job while it is building.
noRenameWhileBuilding=N\u00e3o \u00e9 poss\u00edvel renomear enquanto o job est\u00e1 em constru\u00e7\u00e3o
# Yes
Yes=Sim
# No
# All other configuration options were saved.
configWasSaved=Todas as outras op\u00e7\u00f5es de configura\u00e7\u00e3o foram salvas
# Are you sure about renaming {0} to {1}?
description=Tem certeza que quer renomear {0} para {1}?
# The name {0} is already in use.
newNameInUse=O nome {0} j\u00e1 esta em uso.
# This file is under the MIT License by authors
No=\u041d\u0435\u0442
Yes=\u0414\u0430
description=\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c {0} \u0432 {1}?
noRenameWhileBuilding=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043a\u0430\u0445
newNameInUse=\u0417\u0430\u0434\u0430\u0447\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c {0} \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
configWasSaved=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b
# This file is under the MIT License by authors
noRenameWhileBuilding=\u041D\u0438\u0458\u0435 \u043C\u043E\u0433\u0443\u045B\u0435 \u043F\u0440\u0435\u0438\u043C\u0435\u043D\u043E\u0432\u0430\u0442\u0438 \u0437\u0430\u0434\u0430\u0442\u0430\u043A \u0434\u043E\u043A \u0441\u0435 \u0433\u0440\u0430\u0434\u0438.
configWasSaved=\u0421\u0432\u0430 \u043F\u043E\u0434\u0435\u0448\u0430\u0432\u0430\u045A\u0430 \u0441\u0443 \u0441\u0430\u0447\u0443\u0432\u0430\u043D\u0430.
newNameInUse=\u0418\u043C\u0435 {0} \u0458\u0435 \u0437\u0430\u0443\u0437\u0435\u0442\u043E.
description=\u0414\u0430 \u043B\u0438 \u0441\u0442\u0435 \u0441\u0438\u0433\u0443\u0440\u043D\u0438 \u0434\u0430 \u0436\u0435\u043B\u0438\u0442\u0435 \u0434\u0430 \u043F\u0440\u0435\u0438\u043C\u0435\u043D\u0443\u0458\u0435\u0442\u0435 "{0}" \u0443 "{1}"?
Yes=\u0414\u0430
No=\u041D\u0435
# The MIT License
#
# Copyright (c) 2017, suren <zxjlwt@126.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
noRenameWhileBuilding=\u4E0D\u5141\u8BB8\u91CD\u547D\u540D\u6B63\u5728\u6784\u5EFA\u4E2D\u7684\u4EFB\u52A1\u3002
newNameInUse=\u8BE5\u547D\u540D {0} \u5DF2\u7ECF\u88AB\u5360\u7528\u3002
newNameNotValid=\u8BE5\u547D\u540D {0} \u4E0D\u5408\u6CD5\u3002
configWasSaved=All other configuration options were saved.
description=\u4F60\u786E\u5B9A\u628A {0} \u91CD\u547D\u540D\u4E3A {1}\uFF1F
Yes=\u786E\u5B9A
# The MIT License
#
# Copyright (c) 2013, Chunghwa Telecom Co., Ltd., Pei-Tang Huang
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
configWasSaved=\u5176\u4ed6\u8a2d\u5b9a\u9078\u9805\u5df2\u88ab\u5132\u5b58\u3002
noRenameWhileBuilding=\u4f5c\u696d\u5efa\u7f6e\u4e2d\uff0c\u7121\u6cd5\u6539\u540d\u3002
newNameInUse={0} \u9019\u500b\u540d\u5b57\u5df2\u7d93\u88ab\u4f7f\u7528\u4e86\u3002
description=\u4F60\u78BA\u5B9A\u8981\u5C07 {0} \u6539\u540D\u6210 {1}?
Yes=\u662F
No=\u5426
......@@ -35,6 +35,7 @@ AbstractItem.TaskNoun=Build
AbstractItem.BeingDeleted={0} is currently being deleted
AbstractItem.FailureToStopBuilds=Failed to interrupt and stop {0,choice,1#{0,number,integer} build|1<{0,number,integer} \
builds} of {1}
AbstractItem.NewNameInUse=The name \u201c{0}\u201d is already in use.
AbstractProject.AssignedLabelString_NoMatch_DidYouMean=There\u2019s no agent/cloud that matches this assignment. Did you mean \u2018{1}\u2019 instead of \u2018{0}\u2019?
AbstractProject.NewBuildForWorkspace=Scheduling a new build to get a workspace.
AbstractProject.AwaitingBuildForWorkspace=Awaiting build to get a workspace.
......@@ -174,6 +175,7 @@ Item.CREATE.description=Create a new job.
Item.DELETE.description=Delete a job.
Item.CONFIGURE.description=Change the configuration of a job.
Item.READ.description=See a job. (You may deny this permission but allow Discover to force an anonymous user to log in to see the job.)
Item.RENAME.description=Rename a job.
ItemGroupMixIn.may_not_copy_as_it_contains_secrets_and_=May not copy {0} as it contains secrets and {1} has {2}/{3} but not /{4}
Job.AllRecentBuildFailed=All recent builds failed.
Job.BuildStability=Build stability: {0}
......@@ -181,7 +183,7 @@ Job.NOfMFailed={0} out of the last {1} builds failed.
Job.NoRecentBuildFailed=No recent builds failed.
Job.Pronoun=Project
Job.minutes=mins
Job.NoRenameWhileBuilding=Unable to rename a job while it is building.
Job.you_must_use_the_save_button_if_you_wish=You must use the Save button if you wish to rename a job.
Label.GroupOf=group of {0}
Label.InvalidLabel=invalid label
......@@ -383,7 +385,7 @@ BuildAuthorizationToken.InvalidTokenProvided=Invalid token provided.
Jenkins.CheckDisplayName.NameNotUniqueWarning=The display name, "{0}", is used as a name by a job and could cause confusing search results.
Jenkins.CheckDisplayName.DisplayNameNotUniqueWarning=The display name, "{0}", is already in use by another job and could cause confusion and delay.
Jenkins.NotAllowedName="{0}" is not allowed name
Jenkins.NotAllowedName=\u201c{0}\u201d is not an allowed name
Jenkins.IsRestarting=Jenkins is restarting
User.IllegalUsername="{0}" is prohibited as a username for security reasons.
......
......@@ -37,6 +37,8 @@ AbstractItem.NoSuchJobExistsWithoutSuggestion=\
\u041d\u0435 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0430 \u0438\u043c\u0435 \u201e{0}\u201c.
AbstractItem.Pronoun=\
\u0415\u043b\u0435\u043c\u0435\u043d\u0442
AbstractItem.NewNameInUse=\
\u0418\u043c\u0435\u0442\u043e \u201e{0}\u201c \u0435 \u0437\u0430\u0435\u0442\u043e.
AbstractProject.NewBuildForWorkspace=\
\u041d\u0430\u0441\u0440\u043e\u0447\u0432\u0430\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432\u043e \u0438\u0437\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0435, \u0437\u0430 \u0434\u0430 \u0441\u0435 \u043f\u043e\u043b\u0443\u0447\u0438 \u0440\u0430\u0431\u043e\u0442\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e.
AbstractProject.AwaitingBuildForWorkspace=\
......@@ -260,7 +262,8 @@ Job.Pronoun=\
\u041f\u0440\u043e\u0435\u043a\u0442
Job.minutes=\
\u043c\u0438\u043d.
Job.NoRenameWhileBuilding=\
\u041d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u043e \u0432\u0440\u0435\u043c\u0435 \u043d\u0430 \u043d\u0435\u0439\u043d\u043e\u0442\u043e \u0438\u0437\u0433\u0440\u0430\u0436\u0434\u0430\u043d\u0435 .
Job.you_must_use_the_save_button_if_you_wish=\
\u0417\u0430 \u0434\u0430 \u043f\u0440\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u0442\u0435 \u0437\u0430\u0434\u0430\u0447\u0430, \u043d\u0430\u0442\u0438\u0441\u043d\u0435\u0442\u0435 \u0431\u0443\u0442\u043e\u043d\u0430 \u201e\u0417\u0430\u043f\u0430\u0437\u0432\u0430\u043d\u0435\u201c.
Label.GroupOf=\
......
......@@ -216,3 +216,5 @@ HealthReport.EmptyString=
MultiStageTimeSeries.EMPTY_STRING=
ManageJenkinsAction.DisplayName=Bestyr Jenkins
ParametersDefinitionProperty.DisplayName=Dette byg er parameteriseret
AbstractItem.NewNameInUse=Navnet {0} er allerede i brug
Job.NoRenameWhileBuilding=Kan ikke omd\u00f8be et job imens det bygger
\ No newline at end of file
......@@ -29,6 +29,7 @@ AbstractBuild.KeptBecause=Aufbewahrt wegen {0}
AbstractItem.NoSuchJobExists=Element \u201E{0}\u201C existiert nicht. Meinten Sie vielleicht \u201E{1}\u201C?
AbstractItem.NoSuchJobExistsWithoutSuggestion=Es gibt kein Element \u201E{0}\u201C.
AbstractItem.Pronoun=Element
AbstractItem.NewNameInUse=Der Name {0} wird bereits verwendet.
AbstractProject.AssignedLabelString.InvalidBooleanExpression=Ung\u00FCltiger boolscher Ausdruck: \u201E{0}\u201C
AbstractProject.AssignedLabelString.NoMatch=Es gibt keine Agenten oder Clouds, die diesen Label-Ausdruck bedienen.
AbstractProject.AssignedLabelString_NoMatch_DidYouMean=Es gibt keine Knoten oder Clouds f\u00FCr diesen Ausdruck. Meinten Sie \u201E{1}\u201C statt \u201E{0}\u201C?
......@@ -181,6 +182,7 @@ Job.NOfMFailed={0} der letzten {1} Builds schlug fehl.
Job.NoRecentBuildFailed=In letzter Zeit schlug kein Build fehl.
Job.Pronoun=Projekt
Job.minutes=Minuten
Job.NoRenameWhileBuilding=Ein Job kann nicht umbenannt werden, während er gebaut wird.
Job.you_must_use_the_save_button_if_you_wish=Um das Projekt umzubennen, m\u00FCssen Sie die Schaltfl\u00E4che \u201ESpeichern\u201C verwenden.
Label.GroupOf={0} Gruppe
......
......@@ -25,6 +25,7 @@ AbstractBuild.BuildingOnMaster=Ejecutando en el nodo principal
AbstractBuild.KeptBecause=Conservar porque {0}
AbstractItem.NoSuchJobExists=La tarea ''{0}'' no existe. \u00bfQuiz\u00e1s quieras decir ''{1}''?
AbstractItem.NewNameInUse=El nombre {0} ya existe.
AbstractProject.NewBuildForWorkspace=Lanzando una nueva ejecuci\u00f3n para crear el espacio de trabajo.
AbstractProject.Pronoun=Proyecto
AbstractProject.Aborted=Cancelado
......@@ -118,6 +119,7 @@ Job.NOfMFailed={0} de las {1} \u00faltimas ejecuciones fallaron.
Job.NoRecentBuildFailed=No hay ejecuciones recientes con fallos.
Job.Pronoun=Proyecto
Job.minutes=Min
Job.NoRenameWhileBuilding=No es posible renombrar un proyecto mientras se est ejecutando.
Label.GroupOf=grupo de {0}
Label.InvalidLabel=etiqueta inv\u00e1lida
......
......@@ -34,6 +34,7 @@ AbstractItem.TaskNoun=Compilazione
AbstractItem.BeingDeleted=Eliminazione di {0} in corso
AbstractItem.FailureToStopBuilds=Interruzione e arresto {0,choice,1#{0,number,integer} \
della compilazione|1<{0,number,integer} delle compilazioni} di {1} non riusciti
AbstractItem.NewNameInUse=Il nome {0} è già utilizzato.
AbstractProject.AssignedLabelString_NoMatch_DidYouMean=Non esiste alcun agente/cloud corrispondente a questo assegnamento. Forse si intendeva "{1}" anziché "{0}"?
AbstractProject.NewBuildForWorkspace=Pianificazione di una nuova compilazione per ottenere uno spazio di lavoro in corso.
AbstractProject.AwaitingBuildForWorkspace=In attesa della compilazione per ottenere uno spazio di lavoro.
......@@ -181,7 +182,7 @@ Job.NOfMFailed={0} delle ultime {1} compilazioni non sono riuscite.
Job.NoRecentBuildFailed=Nessuna compilazione recente non riuscita.
Job.Pronoun=Progetto
Job.minutes=min
Job.NoRenameWhileBuilding=Impossibile rinominare un processo finché la sua compilazione è in corso.
Job.you_must_use_the_save_button_if_you_wish=È necessario utilizzare il pulsante Salva se si desidera rinominare un processo.
Label.GroupOf=gruppo di {0}
Label.InvalidLabel=etichetta non valida
......
......@@ -28,6 +28,7 @@ AbstractBuild.KeptBecause={0}\u306e\u305f\u3081\u3001\u4fdd\u5b58\u3057\u307e\u3
AbstractItem.NoSuchJobExists=\u30b8\u30e7\u30d6''{0}''\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002''{1}''\u3067\u3059\u304b?
AbstractItem.Pronoun=\u30b8\u30e7\u30d6
AbstractItem.NewNameInUse=\u30b8\u30e7\u30d6\u540d {0} \u306f\u3059\u3067\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002
AbstractProject.NewBuildForWorkspace=\u65b0\u898f\u306e\u30d3\u30eb\u30c9\u3092\u5b9f\u884c\u3057\u3066\u3001\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u3092\u4f5c\u6210\u3057\u3066\u304f\u3060\u3055\u3044\u3002
AbstractProject.AwaitingBuildForWorkspace=\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u304c\u7528\u610f\u3067\u304d\u308b\u307e\u3067\u30d3\u30eb\u30c9\u3092\u4fdd\u7559\u3057\u307e\u3059\u3002
AbstractProject.Pronoun=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
......@@ -140,6 +141,7 @@ Job.NOfMFailed=\u6700\u8fd1\u306e{1}\u500b\u4e2d\u3001{0}\u500b\u30d3\u30eb\u30c
Job.NoRecentBuildFailed=\u6700\u8fd1\u306e\u30d3\u30eb\u30c9\u306f\u5931\u6557\u3057\u3066\u307e\u305b\u3093\u3002
Job.Pronoun=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8
Job.minutes=\u5206
Job.NoRenameWhileBuilding=\u30d3\u30eb\u30c9\u4e2d\u306b\u30b8\u30e7\u30d6\u540d\u3092\u5909\u66f4\u3067\u304d\u307e\u305b\u3093\u3002
Label.GroupOf={0}
Label.InvalidLabel=\u4e0d\u6b63\u306a\u30e9\u30d9\u30eb
......
......@@ -23,6 +23,8 @@
AbstractBuild.BuildingRemotely=Construindo remotamente em {0}
AbstractBuild.KeptBecause=mantido por causa de {0}
AbstractItem.NewNameInUse=O nome {0} j\u00e1 esta em uso.
AbstractProject.Pronoun=Projeto
AbstractProject.Aborted=Abortado
AbstractProject.Disabled=builds desabilitada
......@@ -74,6 +76,7 @@ Job.NOfMFailed={0} das ultimas {1} builds falharam.
Job.NoRecentBuildFailed=Nenhuma builds recente falhou.
Job.Pronoun=Projeto
Job.minutes=minutos
Job.NoRenameWhileBuilding=N\u00e3o \u00e9 poss\u00edvel renomear enquanto o job est\u00e1 em constru\u00e7\u00e3o
Queue.BlockedBy=Bloqueado por {0}
Queue.InProgress=Uma builds j\u00e1 esta em progresso
......
......@@ -23,6 +23,8 @@
AbstractBuild.BuildingRemotely=\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e \u043d\u0430 {0}
AbstractBuild.KeptBecause=\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e {0}
AbstractItem.NewNameInUse=\u0417\u0430\u0434\u0430\u0447\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c {0} \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442.
AbstractProject.Pronoun=\u041f\u0440\u043e\u0435\u043a\u0442
AbstractProject.Aborted=\u041f\u0440\u0435\u0440\u0432\u0430\u043d\u043e
AbstractProject.Disabled=\u0421\u0431\u043e\u0440\u043a\u0430 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430
......@@ -78,6 +80,7 @@ Job.NOfMFailed={0} \u0438\u0437 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438
Job.NoRecentBuildFailed=\u0421\u0440\u0435\u0434\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0432\u0448\u0438\u0445\u0441\u044f \u043d\u0435\u0442.
Job.Pronoun=\u041f\u0440\u043e\u0435\u043a\u0442
Job.minutes=\u043c\u0438\u043d
Job.NoRenameWhileBuilding=\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u043f\u0440\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043a\u0430\u0445
Queue.BlockedBy=\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e {0}
Queue.InProgress=\u0421\u0431\u043e\u0440\u043a\u0430 \u0443\u0436\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435
......
......@@ -8,6 +8,7 @@ AbstractBuild.KeptBecause=\u041E\u0432\u043E \u0438\u0437\u0433\u0440\u0430\u043
AbstractItem.NoSuchJobExists=\u041D\u0435 \u043F\u043E\u0441\u0442\u043E\u0458\u0438 \u0437\u0430\u0434\u0430\u0442\u0430\u043A "{0}". \u0414\u0430 \u043B\u0438 \u0441\u0442\u0435 \u0438\u043C\u0430\u043B\u0438 "{1}"?
AbstractItem.NoSuchJobExistsWithoutSuggestion=\u041D\u0435 \u043F\u043E\u0441\u0442\u043E\u0458\u0438 \u0437\u0430\u0434\u0430\u0442\u0430\u043A \u0441\u0430 \u0438\u043C\u0435\u043D\u043E\u043C "{0}".
AbstractItem.Pronoun=\u043E\u0431\u0458\u0435\u043A\u0430\u0442
AbstractItem.NewNameInUse=\u0418\u043C\u0435 {0} \u0458\u0435 \u0437\u0430\u0443\u0437\u0435\u0442\u043E.
AbstractProject.AssignedLabelString_NoMatch_DidYouMean=\u041D\u0435\u043C\u0430 \u0442\u0430\u043A\u0432\u043E\u0433 \u0430\u0433\u0435\u043D\u0442\u0430/cloud. \u0414\u0430 \u043B\u0438 \u0441\u0442\u0435 \u043C\u0438\u0441\u043B\u0438\u043B\u0438 "{1}" \u043D\u0430 \u0443\u043C\u0443 \u0443\u043C\u0435\u0441\u0442\u043E "{0}"?
AbstractProject.NewBuildForWorkspace=\u0417\u0430\u043A\u0430\u0437\u0438\u0432\u0430\u045A\u0435 \u043D\u043E\u0432\u0435 \u0438\u0437\u0433\u0440\u0430\u0434\u045A\u0435 \u0434\u0430 \u0431\u0438 \u0441\u0435 \u0434\u043E\u0431\u0438\u043E \u043D\u043E\u0432\u0438 \u0440\u0430\u0434\u043D\u0438 \u043F\u0440\u043E\u0441\u0442\u043E\u0440.
AbstractProject.Pronoun=\u041F\u0440\u043E\u0458\u0435\u043A\u0430\u0442
......@@ -132,6 +133,7 @@ Job.NOfMFailed={0} \u043E\u0434 \u043F\u043E\u0441\u043B\u0435\u0434\u045A\u0438
Job.NoRecentBuildFailed=\u0418\u0437\u043C\u0435\u045B\u0443 \u043D\u0430\u0458\u043D\u043E\u0432\u0438\u0458\u0438\u0445 \u0438\u0437\u0433\u0440\u0430\u0434\u045A\u0430 \u043D\u0435\u043C\u0430 \u043D\u0435\u0443\u0441\u043F\u0435\u0448\u043D\u0438\u0445.
Job.Pronoun=\u041F\u0440\u043E\u0458\u0435\u043A\u0430\u0442
Job.minutes=\u043C\u0438\u043D.
Job.NoRenameWhileBuilding=\u041D\u0438\u0458\u0435 \u043C\u043E\u0433\u0443\u045B\u0435 \u043F\u0440\u0435\u0438\u043C\u0435\u043D\u043E\u0432\u0430\u0442\u0438 \u0437\u0430\u0434\u0430\u0442\u0430\u043A \u0434\u043E\u043A \u0441\u0435 \u0433\u0440\u0430\u0434\u0438.
Job.you_must_use_the_save_button_if_you_wish=\u0414\u0430 \u043F\u0440\u0435\u0438\u043C\u0435\u043D\u0443\u0458\u0442\u0435 \u0437\u0430\u0434\u0430\u0442\u0430\u043A, \u043A\u043B\u0438\u043A\u043D\u0438\u0442\u0435 \u043D\u0430 \u0434\u0443\u0433\u043C\u0435 "\u0421\u0430\u0447\u0443\u0432\u0430\u0458".
Label.GroupOf=\u0433\u0440\u0443\u043F\u0430 {0}
Label.InvalidLabel=\u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u043D\u0430 \u043B\u0430\u0431\u0435\u043B\u0430
......
......@@ -56,6 +56,7 @@ Node.Mode.EXCLUSIVE=\u53EA\u5141\u8BB8\u8FD0\u884C\u7ED1\u5B9A\u5230\u8FD9\u53F0
MyView.DisplayName=\u6211\u7684\u89C6\u56FE
AbstractItem.Pronoun=\u4EFB\u52A1
AbstractItem.NewNameInUse=\u8BE5\u547D\u540D {0} \u5DF2\u7ECF\u88AB\u5360\u7528\u3002
MyViewsProperty.DisplayName=\u6211\u7684\u89C6\u56FE
MyViewsProperty.GlobalAction.DisplayName=\u6211\u7684\u89C6\u56FE
......@@ -73,3 +74,5 @@ ChoiceParameterDefinition.DisplayName=\u9009\u9879\u53C2\u6570
ChoiceParameterDefinition.MissingChoices=\u9700\u8981\u9009\u9879\u3002
RunParameterDefinition.DisplayName=\u8FD0\u884C\u65F6\u53C2\u6570
PasswordParameterDefinition.DisplayName=\u5BC6\u7801\u53C2\u6570
Job.NoRenameWhileBuilding=\u4E0D\u5141\u8BB8\u91CD\u547D\u540D\u6B63\u5728\u6784\u5EFA\u4E2D\u7684\u4EFB\u52A1\u3002
......@@ -29,6 +29,7 @@ AbstractBuild.KeptBecause=\u56e0\u70ba {0} \u800c\u4fdd\u7559
AbstractItem.NoSuchJobExists=\u6c92\u6709 ''{0}'' \u4f5c\u696d\u3002\u60a8\u6307\u7684\u662f ''{1}'' \u55ce?
AbstractItem.Pronoun=\u4f5c\u696d
AbstractItem.NewNameInUse={0} \u9019\u500b\u540d\u5b57\u5df2\u7d93\u88ab\u4f7f\u7528\u4e86\u3002
AbstractProject.NewBuildForWorkspace=\u6311\u500b\u6642\u9593\u5efa\u7f6e\uff0c\u5c31\u80fd\u7522\u751f\u5de5\u4f5c\u5340\u3002
AbstractProject.AwaitingBuildForWorkspace=\u7b49\u5019\u5efa\u7f6e\u7522\u51fa\u5de5\u4f5c\u5340\u3002
AbstractProject.Pronoun=\u5c08\u6848
......@@ -141,6 +142,7 @@ Job.NOfMFailed=\u6700\u8fd1 {1} \u6b21\u5efa\u7f6e\u4e2d\u6709 {0} \u6b21\u5931\
Job.NoRecentBuildFailed=\u6700\u8fd1\u5e7e\u6b21\u5efa\u7f6e\u90fd\u6c92\u6709\u5931\u6557\u3002
Job.Pronoun=\u5c08\u6848
Job.minutes=\u5206
Job.NoRenameWhileBuilding=\u4f5c\u696d\u5efa\u7f6e\u4e2d\uff0c\u7121\u6cd5\u6539\u540d\u3002
Label.GroupOf={0} \u7fa4\u7d44
Label.InvalidLabel=\u6a19\u7c64\u7121\u6548
......
<!--
The MIT License
Copyright 2018 CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:s="/lib/form">
<!-- TODO: Should use permission attribute after JENKINS-18649 -->
<j:if test="${it.hasPermission(it.CONFIGURE) or (it.parent.hasPermission(it.CREATE) and it.hasPermission(it.DELETE))}">
<l:task href="${url}/confirm-rename" icon="icon-notepad icon-md" enabled="${it.nameEditable}" title="${%Rename}"/>
</j:if>
</j:jelly>
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import hudson.security.ACL;
import hudson.security.ACLContext;
import hudson.security.AccessDeniedException2;
import hudson.util.FormValidation;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import jenkins.model.Jenkins;
import jenkins.model.ProjectNamingStrategy;
import org.apache.commons.io.FileUtils;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.SleepBuilder;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class AbstractItemTest {
......@@ -40,4 +59,87 @@ public class AbstractItemTest {
assertEquals(b.getDescription(), b2.getDescription()); // but should have the same properties
}
@Test
public void checkRenameValidity() throws Exception {
FreeStyleProject p = j.createFreeStyleProject("foo");
p.getBuildersList().add(new SleepBuilder(10));
assertThat(checkNameAndReturnError(p, ""), equalTo(Messages.Hudson_NoName()));
assertThat(checkNameAndReturnError(p, ".."), equalTo(Messages.Jenkins_NotAllowedName("..")));
assertThat(checkNameAndReturnError(p, "50%"), equalTo(Messages.Hudson_UnsafeChar('%')));
assertThat(checkNameAndReturnError(p, "foo"), equalTo(Messages.AbstractItem_NewNameInUse("foo")));
j.jenkins.setProjectNamingStrategy(new ProjectNamingStrategy.PatternProjectNamingStrategy("bar", "", false));
assertThat(checkNameAndReturnError(p, "foo1"), equalTo(jenkins.model.Messages.Hudson_JobNameConventionNotApplyed("foo1", "bar")));
p.scheduleBuild2(0).waitForStart();
assertThat(checkNameAndReturnError(p, "bar"), equalTo(Messages.Job_NoRenameWhileBuilding()));
}
@Test
public void checkRenamePermissions() throws Exception {
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
MockAuthorizationStrategy mas = new MockAuthorizationStrategy();
mas.grant(Item.CONFIGURE).everywhere().to("alice", "bob");
mas.grant(Item.READ).everywhere().to("alice");
j.jenkins.setAuthorizationStrategy(mas);
FreeStyleProject p = j.createFreeStyleProject("foo");
try (ACLContext unused = ACL.as(User.getById("alice", true))) {
assertThat(checkNameAndReturnError(p, "foo"), equalTo(Messages.AbstractItem_NewNameInUse("foo")));
}
try (ACLContext unused = ACL.as(User.getById("bob", true))) {
assertThat(checkNameAndReturnError(p, "foo"), equalTo(Messages.Jenkins_NotAllowedName("foo")));
}
try (ACLContext unused = ACL.as(User.getById("carol", true))) {
try {
p.doCheckNewName("foo");
fail("Expecting AccessDeniedException");
} catch (AccessDeniedException2 e) {
assertThat(e.permission, equalTo(Item.CREATE));
}
}
}
@Test
public void renameViaRestApi() throws Exception {
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
MockAuthorizationStrategy mas = new MockAuthorizationStrategy();
mas.grant(Item.READ, Jenkins.READ).everywhere().to("alice", "bob");
mas.grant(Item.CONFIGURE).everywhere().to("alice");
j.jenkins.setAuthorizationStrategy(mas);
FreeStyleProject p = j.createFreeStyleProject("foo");
WebClient w = j.createWebClient();
WebRequest wr = new WebRequest(w.createCrumbedUrl(p.getUrl() + "confirmRename"), HttpMethod.POST);
wr.setRequestParameters(Arrays.asList(new NameValuePair("newName", "bar")));
w.login("alice", "alice");
assertThat(getPath(w.getPage(wr).getUrl()), equalTo(p.getUrl()));
assertThat(p.getName(), equalTo("bar"));
wr = new WebRequest(w.createCrumbedUrl(p.getUrl() + "confirmRename"), HttpMethod.POST);
wr.setRequestParameters(Arrays.asList(new NameValuePair("newName", "baz")));
w.login("bob", "bob");
try {
assertThat(getPath(w.getPage(wr).getUrl()), equalTo(p.getUrl()));
fail("Expecting HTTP 403 Forbidden");
} catch (FailingHttpStatusCodeException e) {
assertThat(e.getStatusCode(), equalTo(403));
}
assertThat(p.getName(), equalTo("bar"));
}
private String checkNameAndReturnError(AbstractItem i, String newName) {
FormValidation fv = i.doCheckNewName(newName);
if (FormValidation.Kind.OK.equals(fv.kind)) {
throw new AssertionError("Expecting Failure");
} else {
return fv.getMessage();
}
}
private String getPath(URL u) {
return u.getPath().substring(j.contextPath.length() + 1);
}
}
......@@ -415,27 +415,27 @@ public class JobTest {
@Issue("JENKINS-30502")
@Test
public void testRenameTrimsLeadingSpace() throws Exception {
tryRename("myJob1", " foo", "foo", false);
tryRename("myJob1", " foo", "foo");
}
@Issue("JENKINS-30502")
@Test
public void testRenameTrimsTrailingSpace() throws Exception {
tryRename("myJob2", "foo ", "foo", false);
tryRename("myJob2", "foo ", "foo");
}
@Issue("JENKINS-30502")
@Test
public void testAllowTrimmingByUser() throws Exception {
assumeFalse("Unix-only test.", Functions.isWindows());
tryRename("myJob3 ", "myJob3", "myJob3", false);
tryRename("myJob3 ", "myJob3", "myJob3");
}
@Issue("JENKINS-30502")
@Test
public void testRenameWithLeadingSpaceTrimsLeadingSpace() throws Exception {
assumeFalse("Unix-only test.", Functions.isWindows());
tryRename(" myJob4", " foo", "foo", false);
tryRename(" myJob4", " foo", "foo");
}
@Issue("JENKINS-30502")
......@@ -443,7 +443,7 @@ public class JobTest {
public void testRenameWithLeadingSpaceTrimsTrailingSpace()
throws Exception {
assumeFalse("Unix-only test.", Functions.isWindows());
tryRename(" myJob5", "foo ", "foo", false);
tryRename(" myJob5", "foo ", "foo");
}
@Issue("JENKINS-30502")
......@@ -451,7 +451,7 @@ public class JobTest {
public void testRenameWithTrailingSpaceTrimsTrailingSpace()
throws Exception {
assumeFalse("Unix-only test.", Functions.isWindows());
tryRename("myJob6 ", "foo ", "foo", false);
tryRename("myJob6 ", "foo ", "foo");
}
@Issue("JENKINS-30502")
......@@ -459,14 +459,7 @@ public class JobTest {
public void testRenameWithTrailingSpaceTrimsLeadingSpace()
throws Exception {
assumeFalse("Unix-only test.", Functions.isWindows());
tryRename("myJob7 ", " foo", "foo", false);
}
@Issue("JENKINS-30502")
@Test
public void testDoNotAutoTrimExistingUntrimmedNames() throws Exception {
assumeFalse("Unix-only test.", Functions.isWindows());
tryRename("myJob8 ", "myJob8 ", null, true);
tryRename("myJob7 ", " foo", "foo");
}
@Issue("JENKINS-35160")
......@@ -492,24 +485,17 @@ public class JobTest {
}
private void tryRename(String initialName, String submittedName,
String correctResult, boolean shouldSkipConfirm) throws Exception {
String correctResult) throws Exception {
j.jenkins.setCrumbIssuer(null);
FreeStyleProject job = j.createFreeStyleProject(initialName);
WebClient wc = j.createWebClient();
HtmlForm form = wc.getPage(job, "configure").getFormByName("config");
form.getInputByName("name").setValueAttribute(submittedName);
HtmlForm form = wc.getPage(job, "confirm-rename").getFormByName("config");
form.getInputByName("newName").setValueAttribute(submittedName);
HtmlPage resultPage = j.submit(form);
String urlTemplate;
if (shouldSkipConfirm) {
urlTemplate = "/job/{0}/";
} else {
urlTemplate = "/job/{0}/rename?newName={1}";
}
String urlString = MessageFormat.format(
urlTemplate, initialName, correctResult).replace(" ", "%20");
"/job/{0}/", correctResult).replace(" ", "%20");
assertThat(resultPage.getUrl().toString(), endsWith(urlString));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册