提交 8d79e93d 编写于 作者: J Jesse Glick

Merge branch 'master' into BuildReference-JENKINS-19400

......@@ -26,4 +26,3 @@ All about Jenkins CI can be found on our [website]. Follow us on Twitter @[jenki
[GitHub]: https://github.com/jenkinsci/jenkins
[website]: http://jenkins-ci.org
[jenkinsci]: http://twitter.com/jenkinsci
......@@ -55,13 +55,63 @@ Upcoming changes</a>
<!-- Record your changes in the trunk here. -->
<div id="trunk" style="display:none"><!--=TRUNK-BEGIN=-->
<ul class=image>
<li class=>
<li class='major rfe'>
Added infrastructure for moving items into or out of folders.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20008">issue 20008</a>)
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18028">issue 18028</a>)
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18680">issue 18680</a>)
<li class=bug>
<i>Apply</i> buttons did not work in Internet Explorer in compatibility mode.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-19826">issue 19826</a>)
<li class=bug>
<code>/login</code> offers link to <code>/opensearch.xml</code> which anonymous users cannot retrieve.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21254">issue 21254</a>)
</ul>
</div><!--=TRUNK-END=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
<div id="rc" style="display:none;"><!--=BEGIN=-->
<h3><a name=v1.544>What's new in 1.544</a> <!--=DATE=--></h3>
<h3><a name=v1.547>What's new in 1.547</a> <!--=DATE=--></h3>
<ul class=image>
<li class="major bug">
NPE since 1.545 when using aggregated test result publisher without specifying downstream jobs explicitly.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18410">issue 18410</a>)
<li class=bug>
Fixed Trend Graph NPE when there isn't any builds
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21239">issue 21239</a>)
</ul>
</div><!--=END=-->
<h3><a name=v1.546>What's new in 1.546</a> (2014/01/06)</h3>
<ul class=image>
<li class="major bug">
Builds disappear after renaming a job.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18678">issue 18678</a>)
<li class=bug>
When clicking <i>Apply</i> to rename a job, tell the user that <i>Save</i> must be used instead.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-17401">issue 17401</a>)
<li class="major bug">
Exception from XStream running Maven builds on strange Java versions.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21183">issue 21183</a>)
<li class=bug>
When clicking <i>Apply</i> results in an exception (error page), show it, rather than creating an empty dialog.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20772">issue 20772</a>)
</ul>
<h3><a name=v1.545>What's new in 1.545</a> (2013/12/31)</h3>
<ul class=image>
<li class=bug>
<code>CannotResolveClassException</code> breaks loading of entire containing folder, not just one job.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-20951">issue 20951</a>)
<li class=bug>
Better robustness against XML deserialization errors.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21024">issue 21024</a>)
<li class=bug>
Minimizing disk I/O while loading the <em>names</em> of build records during Jenkins startup.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-21078">issue 21078</a>)
<li class=bug>
Avoiding serializing the owning build as part of a test result action, as this can lead to errors later.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18410">issue 18410</a>)
</ul>
<h3><a name=v1.544>What's new in 1.544</a> (2013/12/15)</h3>
<ul class=image>
<li class=bug>
RingBufferLogHandler throws ArrayIndexOutOfBoundsException after int-overflow.
......@@ -85,7 +135,6 @@ Upcoming changes</a>
JavaScript errors when navigating away from a page with a build timeline widget while the timeline is loading.
(<a href="https://github.com/jenkinsci/jenkins/pull/1041">pull request 1041</a>)
</ul>
</div><!--=END=-->
<h3><a name=v1.543>What's new in 1.543</a> (2013/12/10)</h3>
<ul class=image>
<li class=bug>
......
......@@ -5,7 +5,7 @@
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.545-SNAPSHOT</version>
<version>1.548-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.545-SNAPSHOT</version>
<version>1.548-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......@@ -219,7 +219,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>xstream</artifactId>
<version>1.4.4-jenkins-4</version>
<version>1.4.4-jenkins-5</version>
</dependency>
<dependency>
<groupId>jfree</groupId>
......@@ -517,14 +517,9 @@ THE SOFTWARE.
<version>1.9</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>jinterop-wmi</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>windows-remote-command</artifactId>
<version>1.4</version>
<groupId>org.kohsuke.jinterop</groupId>
<artifactId>j-interop</artifactId>
<version>2.0.6-kohsuke-1</version>
</dependency>
<dependency>
<groupId>org.kohsuke.metainf-services</groupId>
......@@ -640,7 +635,6 @@ THE SOFTWARE.
<plugin>
<groupId>com.infradna.tool</groupId>
<artifactId>bridge-method-injector</artifactId>
<version>1.9</version>
<executions>
<execution>
<goals>
......@@ -787,7 +781,7 @@ THE SOFTWARE.
<plugin><!-- generate Jelly tag lib documentation -->
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<!-- version specified in grandparent pom -->
<version>${maven-stapler-plugin.version}</version>
<configuration>
<patterns>
<pattern>/lib/.*</pattern>
......
......@@ -272,7 +272,8 @@ public class ClassicPluginStrategy implements PluginStrategy {
new DetachedPlugin("ldap","1.467.*","1.0"),
new DetachedPlugin("pam-auth","1.467.*","1.0"),
new DetachedPlugin("mailer","1.493.*","1.2"),
new DetachedPlugin("matrix-auth","1.535.*","1.0.2")
new DetachedPlugin("matrix-auth","1.535.*","1.0.2"),
new DetachedPlugin("windows-slaves","1.547.*","1.0")
);
/**
......
......@@ -1826,8 +1826,8 @@ public class Functions {
*/
public static String breakableString(final String plain) {
return plain.replaceAll("(\\p{Punct}+\\w)", "<wbr>$1")
.replaceAll("(\\w{10})(?=\\w{3})", "$1<wbr>")
return plain.replaceAll("([\\p{Punct}&&[^;]]+\\w)", "<wbr>$1")
.replaceAll("([^\\p{Punct}\\s-]{10})(?=[^\\p{Punct}\\s-]{3})", "$1<wbr>")
;
}
......
......@@ -24,7 +24,7 @@
package hudson;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.StreamException;
......@@ -140,9 +140,7 @@ public final class XmlFile {
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
return xs.fromXML(in);
} catch(StreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(ConversionException e) {
} catch (XStreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(Error e) {// mostly reflection errors
throw new IOException("Unable to read "+file,e);
......@@ -163,9 +161,7 @@ public final class XmlFile {
try {
// TODO: expose XStream the driver from XStream
return xs.unmarshal(DEFAULT_DRIVER.createReader(in), o);
} catch (StreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(ConversionException e) {
} catch (XStreamException e) {
throw new IOException("Unable to read "+file,e);
} catch(Error e) {// mostly reflection errors
throw new IOException("Unable to read "+file,e);
......
......@@ -299,7 +299,7 @@ public class LogRecorder extends AbstractModelObject implements Saveable {
* The file we save our configuration.
*/
private XmlFile getConfigFile() {
return new XmlFile(XSTREAM, new File(Jenkins.getInstance().getRootDir(),"log/"+name+".xml"));
return new XmlFile(XSTREAM, new File(LogRecorderManager.configDir(), name + ".xml"));
}
/**
......
......@@ -33,7 +33,6 @@ import hudson.model.RSS;
import hudson.util.CopyOnWriteMap;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.ModelObjectWithContextMenu;
import jenkins.model.ModelObjectWithContextMenu.ContextMenu;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.kohsuke.stapler.QueryParameter;
......@@ -52,7 +51,6 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
......@@ -84,12 +82,16 @@ public class LogRecorderManager extends AbstractModelObject implements ModelObje
return logRecorders.get(token);
}
static File configDir() {
return new File(Jenkins.getInstance().getRootDir(), "log");
}
/**
* Loads the configuration from disk.
*/
public void load() throws IOException {
logRecorders.clear();
File dir = new File(Jenkins.getInstance().getRootDir(), "log");
File dir = configDir();
File[] files = dir.listFiles((FileFilter)new WildcardFileFilter("*.xml"));
if(files==null) return;
for (File child : files) {
......
......@@ -34,6 +34,7 @@ import hudson.cli.declarative.CLIMethod;
import hudson.cli.declarative.CLIResolver;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.remoting.Callable;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.security.ACL;
......@@ -224,6 +225,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
+ " already exists");
String oldName = this.name;
String oldFullName = getFullName();
File oldRoot = this.getRootDir();
doSetName(newName);
......@@ -294,8 +296,7 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
callOnRenamed(newName, parent, oldName);
for (ItemListener l : ItemListener.all())
l.onRenamed(this, oldName, newName);
ItemListener.fireLocationChange(this, oldFullName);
}
}
}
......@@ -588,17 +589,17 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
new StreamResult(out));
out.close();
} catch (TransformerException e) {
throw new IOException("Failed to persist configuration.xml", e);
throw new IOException("Failed to persist config.xml", e);
}
// try to reflect the changes by reloading
new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(this);
Items.updatingByXml.set(true);
try {
onLoad(getParent(), getRootDir().getName());
} finally {
Items.updatingByXml.set(false);
}
Items.whileUpdatingByXml(new Callable<Void,IOException>() {
@Override public Void call() throws IOException {
onLoad(getParent(), getRootDir().getName());
return null;
}
});
Jenkins.getInstance().rebuildDependencyGraphAsync();
// if everything went well, commit this new version
......
......@@ -326,8 +326,9 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
}
this.builds = builds;
triggers().setOwner(this);
for (Trigger t : triggers())
t.start(this, Items.updatingByXml.get());
for (Trigger t : triggers()) {
t.start(this, Items.currentlyUpdatingByXml());
}
if(scm==null)
scm = new NullSCM(); // perhaps it was pointing to a plugin that no longer exists.
......@@ -1676,6 +1677,13 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
updateTransientActions();
}
@Override
public void renameTo(String newName) throws IOException {
super.renameTo(newName);
// Update locations inside builds cache
builds.updateBaseDir(getBuildDir());
}
protected final synchronized <T extends Describable<T>>
void removeFromList(Descriptor<T> item, List<T> collection) throws IOException {
final Iterator<T> iCollection = collection.iterator();
......@@ -2119,6 +2127,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
makeDisabled(false);
return new HttpRedirect(".");
}
/**
* RSS feed for changes in this project.
......
......@@ -81,11 +81,6 @@ public class AllView extends View {
return ""; // there's no configuration page
}
@Override
public void onJobRenamed(Item item, String oldName, String newName) {
// noop
}
@Override
protected void submit(StaplerRequest req) throws IOException, ServletException, FormException {
// noop
......
......@@ -967,7 +967,7 @@ public abstract class Descriptor<T extends Describable<T>> implements Saveable {
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
if (FormApply.isApply(req)) {
FormApply.applyResponse("notificationBar.show(" + quote(getMessage())+ ",notificationBar.defaultOptions.ERROR)")
FormApply.applyResponse("notificationBar.show(" + quote(getMessage())+ ",notificationBar.ERROR)")
.generateResponse(req, rsp, node);
} else {
// for now, we can't really use the field name that caused the problem.
......
......@@ -727,7 +727,7 @@ public class Fingerprint implements ModelObject, Saveable {
@Extension
public static final class ProjectRenameListener extends ItemListener {
@Override
public void onRenamed(Item item, String oldName, String newName) {
public void onLocationChanged(Item item, String oldName, String newName) {
if (item instanceof AbstractProject) {
AbstractProject p = Jenkins.getInstance().getItemByFullName(newName, AbstractProject.class);
if (p != null) {
......
......@@ -23,6 +23,7 @@
*/
package hudson.model;
import hudson.model.listeners.ItemListener;
import java.io.IOException;
import java.util.Collection;
import java.io.File;
......@@ -76,6 +77,7 @@ public interface ItemGroup<T extends Item> extends PersistenceRoot, ModelObject
/**
* Internal method. Called by {@link Item}s when they are renamed by users.
* This is <em>not</em> expected to call {@link ItemListener#onRenamed}, inconsistent with {@link #onDeleted}.
*/
void onRenamed(T item, String oldName, String newName) throws IOException;
......
......@@ -25,6 +25,7 @@ package hudson.model;
import hudson.Util;
import hudson.model.listeners.ItemListener;
import hudson.remoting.Callable;
import hudson.security.AccessControlled;
import hudson.util.CopyOnWriteMap;
import hudson.util.Function1;
......@@ -40,6 +41,8 @@ import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Defines a bunch of static methods to be used as a "mix-in" for {@link ItemGroup}
......@@ -96,10 +99,16 @@ public abstract class ItemGroupMixIn {
CopyOnWriteMap.Tree<K,V> configurations = new CopyOnWriteMap.Tree<K,V>();
for (File subdir : subdirs) {
try {
V item = (V) Items.load(parent,subdir);
// Try to retain the identity of an existing child object if we can.
V item = (V) parent.getItem(subdir.getName());
if (item == null) {
item = (V) Items.load(parent,subdir);
} else {
item.onLoad(parent, subdir.getName());
}
configurations.put(key.call(item), item);
} catch (IOException e) {
e.printStackTrace(); // TODO: logging
Logger.getLogger(ItemGroupMixIn.class.getName()).log(Level.WARNING, "could not load " + subdir, e);
}
}
......@@ -204,12 +213,12 @@ public abstract class ItemGroupMixIn {
Util.copyFile(Items.getConfigFile(src).getFile(),Items.getConfigFile(result).getFile());
// reload from the new config
Items.updatingByXml.set(true);
try {
result = (T)Items.load(parent,result.getRootDir());
} finally {
Items.updatingByXml.set(false);
}
final File rootDir = result.getRootDir();
result = Items.whileUpdatingByXml(new Callable<T,IOException>() {
@Override public T call() throws IOException {
return (T) Items.load(parent, rootDir);
}
});
result.onCopiedFrom(src);
add(result);
......@@ -229,18 +238,17 @@ public abstract class ItemGroupMixIn {
// place it as config.xml
File configXml = Items.getConfigFile(getRootDirFor(name)).getFile();
configXml.getParentFile().mkdirs();
final File dir = configXml.getParentFile();
dir.mkdirs();
try {
IOUtils.copy(xml,configXml);
// load it
TopLevelItem result;
Items.updatingByXml.set(true);
try {
result = (TopLevelItem)Items.load(parent,configXml.getParentFile());
} finally {
Items.updatingByXml.set(false);
}
TopLevelItem result = Items.whileUpdatingByXml(new Callable<TopLevelItem,IOException>() {
@Override public TopLevelItem call() throws IOException {
return (TopLevelItem) Items.load(parent, dir);
}
});
add(result);
ItemListener.fireOnCreated(result);
......@@ -249,7 +257,7 @@ public abstract class ItemGroupMixIn {
return result;
} catch (IOException e) {
// if anything fails, delete the config file to avoid further confusion
Util.deleteRecursive(configXml.getParentFile());
Util.deleteRecursive(dir);
throw e;
}
}
......
......@@ -30,6 +30,8 @@ import hudson.matrix.MatrixProject;
import hudson.matrix.MatrixConfiguration;
import hudson.XmlFile;
import hudson.matrix.Axis;
import hudson.model.listeners.ItemListener;
import hudson.remoting.Callable;
import hudson.triggers.Trigger;
import hudson.util.DescriptorList;
import hudson.util.EditDistance;
......@@ -41,6 +43,8 @@ import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.annotation.CheckForNull;
import jenkins.model.DirectlyModifiableTopLevelItemGroup;
import org.apache.commons.io.FileUtils;
/**
* Convenience methods related to {@link Item}.
......@@ -61,12 +65,41 @@ public class Items {
* @see Trigger#start
* @since 1.482
*/
static final ThreadLocal<Boolean> updatingByXml = new ThreadLocal<Boolean>() {
private static final ThreadLocal<Boolean> updatingByXml = new ThreadLocal<Boolean>() {
@Override protected Boolean initialValue() {
return false;
}
};
/**
* Runs a block while making {@link #currentlyUpdatingByXml} be temporarily true.
* Use this when you are creating or changing an item.
* @param <V> a return value type (may be {@link Void})
* @param <T> an error type (may be {@link Error})
* @param callable a block, typically running {@link #load} or {@link Item#onLoad}
* @return whatever {@code callable} returned
* @throws T anything {@code callable} throws
* @since 1.546
*/
public static <V,T extends Throwable> V whileUpdatingByXml(Callable<V,T> callable) throws T {
updatingByXml.set(true);
try {
return callable.call();
} finally {
updatingByXml.set(false);
}
}
/**
* Checks whether we are in the middle of creating or configuring an item via XML.
* Used to determine the {@code newInstance} parameter for {@link Trigger#start}.
* @return true if {@link #whileUpdatingByXml} is currently being called, false for example when merely starting Jenkins or reloading from disk
* @since 1.546
*/
public static boolean currentlyUpdatingByXml() {
return updatingByXml.get();
}
/**
* Returns all the registered {@link TopLevelItemDescriptor}s.
*/
......@@ -149,8 +182,8 @@ public class Items {
}
/**
* Compute the relative name of list of items after a rename occurred. Used to manage job references as names in
* plugins to support {@link hudson.model.listeners.ItemListener#onRenamed(hudson.model.Item, String, String)}.
* Computes the relative name of list of items after a rename or move occurred.
* Used to manage job references as names in plugins to support {@link hudson.model.listeners.ItemListener#onLocationChanged}.
* <p>
* In a hierarchical context, when a plugin has a reference to a job as <code>../foo/bar</code> this method will
* handle the relative path as "foo" is renamed to "zot" to compute <code>../zot/bar</code>
......@@ -170,8 +203,11 @@ public class Items {
String canonicalName = getCanonicalName(context, relativeName);
if (canonicalName.equals(oldFullName) || canonicalName.startsWith(oldFullName+'/')) {
String newCanonicalName = newFullName + canonicalName.substring(oldFullName.length());
// relative name points to the renamed item, let's compute the new relative name
newValue.add( computeRelativeNameAfterRenaming(canonicalName, newCanonicalName, relativeName) );
if (relativeName.startsWith("/")) {
newValue.add("/" + newCanonicalName);
} else {
newValue.add(getRelativeNameFrom(newCanonicalName, context.getFullName()));
}
} else {
newValue.add(relativeName);
}
......@@ -179,39 +215,56 @@ public class Items {
return StringUtils.join(newValue, ",");
}
/**
* Compute the relative name of an Item after renaming
*/
private static String computeRelativeNameAfterRenaming(String oldFullName, String newFullName, String relativeName) {
String[] a = oldFullName.split("/");
String[] n = newFullName.split("/");
assert a.length == n.length;
String[] r = relativeName.split("/");
int j = a.length-1;
for(int i=r.length-1;i>=0;i--) {
String part = r[i];
if (part.equals("") && i==0) {
continue;
}
if (part.equals(".")) {
continue;
}
if (part.equals("..")) {
j--;
continue;
}
if (part.equals(a[j])) {
r[i] = n[j];
j--;
// Had difficulty adapting the version in Functions to use no live items, so rewrote it:
static String getRelativeNameFrom(String itemFullName, String groupFullName) {
String[] itemFullNameA = itemFullName.isEmpty() ? new String[0] : itemFullName.split("/");
String[] groupFullNameA = groupFullName.isEmpty() ? new String[0] : groupFullName.split("/");
for (int i = 0; ; i++) {
if (i == itemFullNameA.length) {
if (i == groupFullNameA.length) {
// itemFullName and groupFullName are identical
return ".";
} else {
// itemFullName is an ancestor of groupFullName; insert ../ for rest of groupFullName
StringBuilder b = new StringBuilder();
for (int j = 0; j < groupFullNameA.length - itemFullNameA.length; j++) {
if (j > 0) {
b.append('/');
}
b.append("..");
}
return b.toString();
}
} else if (i == groupFullNameA.length) {
// groupFullName is an ancestor of itemFullName; insert rest of itemFullName
StringBuilder b = new StringBuilder();
for (int j = i; j < itemFullNameA.length; j++) {
if (j > i) {
b.append('/');
}
b.append(itemFullNameA[j]);
}
return b.toString();
} else if (itemFullNameA[i].equals(groupFullNameA[i])) {
// identical up to this point
continue;
} else {
// first mismatch; insert ../ for rest of groupFullName, then rest of itemFullName
StringBuilder b = new StringBuilder();
for (int j = i; j < groupFullNameA.length; j++) {
if (j > i) {
b.append('/');
}
b.append("..");
}
for (int j = i; j < itemFullNameA.length; j++) {
b.append('/').append(itemFullNameA[j]);
}
return b.toString();
}
}
return StringUtils.join(r, '/');
}
/**
* Loads a {@link Item} from a config file.
*
......@@ -300,6 +353,42 @@ public class Items {
return Jenkins.getInstance().getItem(nearest, context, type);
}
/**
* Moves an item between folders (or top level).
* Fires all relevant events but does not verify that the item’s directory is not currently being used in some way (for example by a running build).
* Does not check any permissions.
* @param item some item (job or folder)
* @param destination the destination of the move (a folder or {@link Jenkins}); not the current parent (or you could just call {@link AbstractItem#renameTo})
* @return the new item (usually the same object as {@code item})
* @throws IOException if the move fails, or some subsequent step fails (directory might have already been moved)
* @throws IllegalArgumentException if the move would really be a rename, or the destination cannot accept the item, or the destination already has an item of that name
* @since 1.548
*/
public static <I extends AbstractItem & TopLevelItem> I move(I item, DirectlyModifiableTopLevelItemGroup destination) throws IOException, IllegalArgumentException {
DirectlyModifiableTopLevelItemGroup oldParent = (DirectlyModifiableTopLevelItemGroup) item.getParent();
if (oldParent == destination) {
throw new IllegalArgumentException();
}
// TODO verify that destination is to not equal to, or inside, item
if (!destination.canAdd(item)) {
throw new IllegalArgumentException();
}
String name = item.getName();
if (destination.getItem(name) != null) {
throw new IllegalArgumentException(name + " already exists");
}
String oldFullName = item.getFullName();
// TODO AbstractItem.renameTo has a more baroque implementation; factor it out into a utility method perhaps?
File destDir = destination.getRootDirFor(item);
FileUtils.forceMkdir(destDir.getParentFile());
FileUtils.moveDirectory(item.getRootDir(), destDir);
oldParent.remove(item);
I newItem = destination.add(item, name);
newItem.onLoad(destination, name);
ItemListener.fireLocationChange(newItem, oldFullName);
return newItem;
}
/**
* Used to load/save job configuration.
*
......
......@@ -54,6 +54,7 @@ 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;
......@@ -1144,7 +1145,11 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
// check this error early to avoid HTTP response splitting.
Jenkins.checkGoodName(newName);
namingStrategy.checkName(newName);
rsp.sendRedirect("rename?newName=" + URLEncoder.encode(newName, "UTF-8"));
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);
......@@ -1211,7 +1216,7 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
}
public Graph getBuildTimeGraph() {
return new Graph(getLastBuild().getTimestamp(),500,400) {
return new Graph(getLastBuildTime(),500,400) {
@Override
protected JFreeChart createGraph() {
class ChartLabel implements Comparable<ChartLabel> {
......@@ -1345,6 +1350,16 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
};
}
private Calendar getLastBuildTime() {
final RunT lastBuild = getLastBuild();
if (lastBuild ==null) {
final GregorianCalendar neverBuiltCalendar = new GregorianCalendar();
neverBuiltCalendar.setTimeInMillis(0);
return neverBuiltCalendar;
}
return lastBuild.getTimestamp();
}
/**
* Renames this job.
*/
......
......@@ -28,6 +28,7 @@ import hudson.Extension;
import hudson.Util;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.Descriptor.FormException;
import hudson.model.listeners.ItemListener;
import hudson.util.CaseInsensitiveComparator;
import hudson.util.DescribableList;
import hudson.util.FormValidation;
......@@ -37,13 +38,18 @@ import hudson.views.ViewJobFilter;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.concurrent.GuardedBy;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import net.sf.json.JSONObject;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.HttpResponse;
......@@ -302,12 +308,6 @@ public class ListView extends View implements Saveable {
return HttpResponses.ok();
}
@Override
public synchronized void onJobRenamed(Item item, String oldName, String newName) {
if(jobNames.remove(oldName) && newName!=null)
jobNames.add(newName);
}
/**
* Handles the configuration submission.
*
......@@ -387,4 +387,56 @@ public class ListView extends View implements Saveable {
public static List<ListViewColumn> getDefaultColumns() {
return ListViewColumn.createDefaultInitialColumnList();
}
@Restricted(NoExternalUse.class)
@Extension public static final class Listener extends ItemListener {
@Override public void onLocationChanged(Item item, String oldFullName, String newFullName) {
for (Item g : Jenkins.getInstance().getAllItems()) {
if (g instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) g;
for (View v : vg.getViews()) {
if (v instanceof ListView) {
ListView lv = (ListView) v;
synchronized (lv) {
Set<String> oldJobNames = new HashSet<String>(lv.jobNames);
lv.jobNames.clear();
for (String oldName : oldJobNames) {
lv.jobNames.add(Items.computeRelativeNamesAfterRenaming(oldFullName, newFullName, oldName, vg.getItemGroup()));
}
if (!oldJobNames.equals(lv.jobNames)) {
try {
g.save();
} catch (IOException x) {
Logger.getLogger(ListView.class.getName()).log(Level.WARNING, null, x);
}
}
}
}
}
}
}
}
@Override public void onDeleted(Item item) {
for (Item g : Jenkins.getInstance().getAllItems()) {
if (g instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) g;
for (View v : vg.getViews()) {
if (v instanceof ListView) {
ListView lv = (ListView) v;
synchronized (lv) {
if (lv.jobNames.remove(item.getRelativeNameFrom(vg.getItemGroup()))) {
try {
g.save();
} catch (IOException x) {
Logger.getLogger(ListView.class.getName()).log(Level.WARNING, null, x);
}
}
}
}
}
}
}
}
}
}
/*
* The MIT License
*
* Copyright (c) 2013 Red Hat, 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 hudson.model;
import java.io.IOException;
import javax.annotation.Nonnull;
/**
* {@link ViewGroup} that can be modified.
*
* @author ogondza
* @since 1.545
*/
public interface ModifiableViewGroup extends ViewGroup {
/**
* Add new {@link View} to this {@link ViewGroup}.
*/
public void addView(@Nonnull View view) throws IOException;
}
......@@ -86,11 +86,6 @@ public class MyView extends View {
return ""; // there's no configuration page
}
@Override
public void onJobRenamed(Item item, String oldName, String newName) {
// noop
}
@Override
protected void submit(StaplerRequest req) throws IOException, ServletException, FormException {
// noop
......
......@@ -58,7 +58,7 @@ import org.kohsuke.stapler.StaplerResponse;
*
* @author Tom Huybrechts
*/
public class MyViewsProperty extends UserProperty implements ViewGroup, Action, StaplerFallback {
public class MyViewsProperty extends UserProperty implements ModifiableViewGroup, Action, StaplerFallback {
private String primaryViewName;
/**
......@@ -136,6 +136,7 @@ public class MyViewsProperty extends UserProperty implements ViewGroup, Action,
viewGroupMixIn.onViewRenamed(view,oldName,newName);
}
@Override
public void addView(View view) throws IOException {
viewGroupMixIn.addView(view);
}
......
......@@ -89,13 +89,6 @@ public class ProxyView extends View implements StaplerFallback {
return getProxiedView().contains(item);
}
@Override
public void onJobRenamed(Item item, String oldName, String newName) {
if (oldName.equals(proxiedViewName)) {
proxiedViewName = newName;
}
}
@Override
protected void submit(StaplerRequest req) throws IOException, ServletException, FormException {
String proxiedViewName = req.getSubmittedForm().getString("proxiedViewName");
......
......@@ -194,24 +194,21 @@ public final class RunMap<R extends Run<?,R>> extends AbstractLazyLoadRunMap<R>
final SimpleDateFormat formatter = Run.ID_FORMATTER.get();
return new FilenameFilter() {
public boolean accept(File dir, String name) {
// JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
// or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
// Don't even bother trying.
if (!isCorrectDate(name)) {
LOGGER.log(FINE, "Skipping {0}", new File(dir,name));
@Override public boolean accept(File dir, String name) {
if (name.startsWith("0000")) {
// JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
// or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
// Don't even bother trying.
return false;
}
return !name.startsWith("0000") && new File(dir,name).isDirectory();
}
private boolean isCorrectDate(String name) {
try {
if(formatter.format(formatter.parse(name)).equals(name))
if (formatter.format(formatter.parse(name)).equals(name)) {
return true;
}
} catch (ParseException e) {
// fall through
}
LOGGER.log(FINE, "Skipping {0} in {1}", new Object[] {name, dir});
return false;
}
};
......
......@@ -119,14 +119,7 @@ public class TreeView extends View implements ViewGroup {
return null;
}
@Override
public synchronized void onJobRenamed(Item item, String oldName, String newName) {
if(jobNames.remove(oldName) && newName!=null)
jobNames.add(newName);
// forward to children
for (View v : views)
v.onJobRenamed(item,oldName,newName);
}
// TODO listen for changes that might affect jobNames
protected void submit(StaplerRequest req) throws IOException, ServletException, FormException {
}
......
......@@ -581,21 +581,9 @@ public abstract class View extends AbstractModelObject implements AccessControll
return getACL().hasPermission(p);
}
/**
* Called when a job name is changed or deleted.
*
* <p>
* If this view contains this job, it should update the view membership so that
* the renamed job will remain in the view, and the deleted job is removed.
*
* @param item
* The item whose name is being changed.
* @param oldName
* Old name of the item. Always non-null.
* @param newName
* New name of the item, if the item is renamed. Or null, if the item is removed.
*/
public abstract void onJobRenamed(Item item, String oldName, String newName);
/** @deprecated Does not work properly with moved jobs. Use {@link ItemListener#onLocationChanged} instead. */
@Deprecated
public void onJobRenamed(Item item, String oldName, String newName) {}
@ExportedBean(defaultVisibility=2)
public static final class UserInfo implements Comparable<UserInfo> {
......
......@@ -28,6 +28,8 @@ import hudson.ExtensionList;
import hudson.Extension;
import jenkins.model.Jenkins;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.Items;
/**
* Receives notifications about CRUD operations of {@link Item}.
......@@ -82,7 +84,7 @@ public class ItemListener implements ExtensionPoint {
/**
* Called after a job is renamed.
*
* Most implementers should rather use {@link #onLocationChanged}.
* @param item
* The job being renamed.
* @param oldName
......@@ -94,6 +96,28 @@ public class ItemListener implements ExtensionPoint {
public void onRenamed(Item item, String oldName, String newName) {
}
/**
* Called after an item’s fully-qualified location has changed.
* This might be because:
* <ul>
* <li>This item was renamed.
* <li>Some ancestor folder was renamed.
* <li>This item was moved between folders (or from a folder to Jenkins root or vice-versa).
* <li>Some ancestor folder was moved.
* </ul>
* Where applicable, {@link #onRenamed} will already have been called on this item or an ancestor.
* And where applicable, {@link #onLocationChanged} will already have been called on its ancestors.
* <p>This method should be used (instead of {@link #onRenamed}) by any code
* which seeks to keep (absolute) references to items up to date:
* if a persisted reference matches {@code oldFullName}, replace it with {@code newFullName}.
* @param item an item whose absolute position is now different
* @param oldFullName the former {@link Item#getFullName}
* @param newFullName the current {@link Item#getFullName}
* @see Items#computeRelativeNamesAfterRenaming
* @since 1.548
*/
public void onLocationChanged(Item item, String oldFullName, String newFullName) {}
/**
* Called after a job has its configuration updated.
*
......@@ -141,4 +165,50 @@ public class ItemListener implements ExtensionPoint {
for (ItemListener l : all())
l.onUpdated(item);
}
/** @since 1.548 */
public static void fireOnDeleted(Item item) {
for (ItemListener l : all()) {
l.onDeleted(item);
}
}
/**
* Calls {@link #onRenamed} and {@link #onLocationChanged} as appropriate.
* @param rootItem the topmost item whose location has just changed
* @param oldFullName the previous {@link Item#getFullName}
* @since 1.548
*/
public static void fireLocationChange(Item rootItem, String oldFullName) {
String prefix = rootItem.getParent().getFullName();
if (!prefix.isEmpty()) {
prefix += '/';
}
String newFullName = rootItem.getFullName();
assert newFullName.startsWith(prefix);
int prefixS = prefix.length();
if (oldFullName.startsWith(prefix) && oldFullName.indexOf('/', prefixS) == -1) {
String oldName = oldFullName.substring(prefixS);
String newName = rootItem.getName();
assert newName.equals(newFullName.substring(prefixS));
for (ItemListener l : all()) {
l.onRenamed(rootItem, oldName, newName);
}
}
for (ItemListener l : all()) {
l.onLocationChanged(rootItem, oldFullName, newFullName);
}
if (rootItem instanceof ItemGroup) {
for (Item child : Items.getAllItems((ItemGroup) rootItem, Item.class)) {
String childNew = child.getFullName();
assert childNew.startsWith(newFullName);
assert childNew.charAt(newFullName.length()) == '/';
String childOld = oldFullName + childNew.substring(newFullName.length());
for (ItemListener l : all()) {
l.onLocationChanged(child, childOld, childNew);
}
}
}
}
}
......@@ -265,7 +265,7 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
synchronized(AbstractNodeMonitorDescriptor.this) {
if(inProgress!=null) {
// maybe it got stuck?
LOGGER.warning("Previous "+getDisplayName()+" monitoring activity still in progress. Interrupting");
LOGGER.log(Level.WARNING, "Previous {0} monitoring activity still in progress. Interrupting", getDisplayName());
inProgress.interrupt();
}
inProgress = this;
......@@ -283,7 +283,9 @@ public abstract class AbstractNodeMonitorDescriptor<T> extends Descriptor<NodeMo
timestamp = System.currentTimeMillis();
record = this;
LOGGER.fine("Node monitoring "+getDisplayName()+" completed in "+(System.currentTimeMillis()-startTime)+"ms");
LOGGER.log(Level.FINE, "Node monitoring {0} completed in {1}ms", new Object[] {getDisplayName(), System.currentTimeMillis()-startTime});
} catch (InterruptedException x) {
// interrupted by new one, fine
} catch (Throwable t) {
LOGGER.log(Level.WARNING, "Unexpected node monitoring termination: "+getDisplayName(),t);
} finally {
......
/*
* The MIT License
*
* Copyright (c) 2012-, 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 hudson.os.windows;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.os.windows.ManagedWindowsServiceLauncher.AccountInfo;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* Encapsulates how to login (a part of {@link ManagedWindowsServiceLauncher}).
*
* @author Kohsuke Kawaguchi
* @author Vincent Latombe
* @since 1.448
*/
public abstract class ManagedWindowsServiceAccount extends AbstractDescribableImpl<ManagedWindowsServiceAccount> implements ExtensionPoint {
public abstract AccountInfo getAccount(ManagedWindowsServiceLauncher launcher);
/**
* Logs in with the local system user.
* This is the default.
*/
public static final class LocalSystem extends ManagedWindowsServiceAccount {
@DataBoundConstructor
public LocalSystem() {}
@Override
public AccountInfo getAccount(ManagedWindowsServiceLauncher launcher) {
return null;
}
@Extension(ordinal=100)
public static class DescriptorImpl extends Descriptor<ManagedWindowsServiceAccount> {
@Override
public String getDisplayName() {
return "Use Local System User";
}
}
}
/**
* Logs in with the administrator user account supplied in {@link ManagedWindowsServiceLauncher}.
*/
public static final class Administrator extends ManagedWindowsServiceAccount {
@DataBoundConstructor
public Administrator() {}
@Override
public AccountInfo getAccount(ManagedWindowsServiceLauncher launcher) {
return new AccountInfo(launcher.userName,Secret.toString(launcher.password));
}
@Extension
public static class DescriptorImpl extends Descriptor<ManagedWindowsServiceAccount> {
@Override
public String getDisplayName() {
return "Use Administrator account given above";
}
}
}
/**
* Logs in with a separate user.
*/
public static final class AnotherUser extends ManagedWindowsServiceAccount {
public final String userName;
public final Secret password;
@DataBoundConstructor
public AnotherUser(String userName, Secret password) {
this.userName = userName;
this.password = password;
}
@Override
public AccountInfo getAccount(ManagedWindowsServiceLauncher launcher) {
return new AccountInfo(userName,Secret.toString(password));
}
@Extension
public static class DescriptorImpl extends Descriptor<ManagedWindowsServiceAccount> {
@Override
public String getDisplayName() {
return "Log on using a different account";
}
}
}
}
package hudson.os.windows;
import hudson.Extension;
import hudson.model.TaskListener;
import hudson.slaves.ComputerConnector;
import hudson.slaves.ComputerConnectorDescriptor;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;
import java.io.IOException;
/**
* {@link ComputerConnector} that delegates to {@link ManagedWindowsServiceLauncher}.
* @author Kohsuke Kawaguchi
*/
public class ManagedWindowsServiceConnector extends ComputerConnector {
/**
* "[DOMAIN\\]USERNAME" to follow the Windows convention.
*/
public final String userName;
public final Secret password;
@DataBoundConstructor
public ManagedWindowsServiceConnector(String userName, String password) {
this.userName = userName;
this.password = Secret.fromString(password);
}
@Override
public ManagedWindowsServiceLauncher launch(final String hostName, TaskListener listener) throws IOException, InterruptedException {
return new ManagedWindowsServiceLauncher(userName,Secret.toString(password),hostName);
}
@Extension
public static class DescriptorImpl extends ComputerConnectorDescriptor {
public String getDisplayName() {
return Messages.ManagedWindowsServiceLauncher_DisplayName();
}
// used by Jelly
public static final Class<?> CONFIG_DELEGATE_TO = ManagedWindowsServiceLauncher.class;
}
}
package hudson.os.windows;
import hudson.tools.JDKInstaller.FileSystem;
import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.List;
import static java.util.Arrays.asList;
/**
* {@link FileSystem} implementation for remote Windows system.
*
* @author Kohsuke Kawaguchi
*/
public class WindowsRemoteFileSystem implements FileSystem {
private final String hostName;
private final NtlmPasswordAuthentication auth;
public WindowsRemoteFileSystem(String hostName, NtlmPasswordAuthentication auth) {
this.hostName = hostName;
this.auth = auth;
}
private SmbFile $(String path) throws MalformedURLException {
return new SmbFile("smb://" + hostName + "/" + path.replace('\\', '/').replace(':', '$')+"/",auth);
}
public void delete(String file) throws IOException, InterruptedException {
$(file).delete();
}
public void chmod(String file, int mode) throws IOException, InterruptedException {
// no-op on Windows
}
public InputStream read(String file) throws IOException {
return $(file).getInputStream();
}
public List<String> listSubDirectories(String dir) throws IOException, InterruptedException {
return asList($(dir).list());
}
public void pullUp(String from, String to) throws IOException, InterruptedException {
SmbFile src = $(from);
SmbFile dst = $(to);
for (SmbFile e : src.listFiles()) {
e.renameTo(new SmbFile(dst,e.getName()));
}
src.delete();
}
public void mkdirs(String path) throws IOException {
$(path).mkdirs();
}
}
package hudson.os.windows;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import hudson.Util;
import hudson.model.Computer;
import hudson.model.TaskListener;
import hudson.remoting.Channel;
import hudson.util.StreamCopyThread;
import org.jinterop.dcom.common.JIException;
import org.jvnet.hudson.remcom.WindowsRemoteProcessLauncher;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import static java.util.Arrays.asList;
/**
* Pseudo-{@link Launcher} implementation that uses {@link WindowsRemoteProcessLauncher}
*
* @author Kohsuke Kawaguchi
*/
public class WindowsRemoteLauncher extends Launcher {
private final WindowsRemoteProcessLauncher launcher;
public WindowsRemoteLauncher(TaskListener listener, WindowsRemoteProcessLauncher launcher) {
super(listener,null);
this.launcher = launcher;
}
private String buildCommandLine(ProcStarter ps) {
StringBuilder b = new StringBuilder();
for (String cmd : ps.cmds()) {
if (b.length()>0) b.append(' ');
if (cmd.indexOf(' ')>=0)
b.append('"').append(cmd).append('"');
else
b.append(cmd);
}
return b.toString();
}
public Proc launch(ProcStarter ps) throws IOException {
maskedPrintCommandLine(ps.cmds(), ps.masks(), ps.pwd());
// TODO: environment variable handling
String name = ps.cmds().toString();
final Process proc;
try {
proc = launcher.launch(buildCommandLine(ps), ps.pwd().getRemote());
} catch (JIException e) {
throw new IOException(e);
} catch (InterruptedException e) {
throw new IOException(e);
}
final Thread t1 = new StreamCopyThread("stdout copier: "+name, proc.getInputStream(), ps.stdout(),false);
t1.start();
final Thread t2 = new StreamCopyThread("stdin copier: "+name,ps.stdin(), proc.getOutputStream(),true);
t2.start();
return new Proc() {
public boolean isAlive() throws IOException, InterruptedException {
try {
proc.exitValue();
return false;
} catch (IllegalThreadStateException e) {
return true;
}
}
public void kill() throws IOException, InterruptedException {
t1.interrupt();
t2.interrupt();
proc.destroy();
}
public int join() throws IOException, InterruptedException {
try {
t1.join();
t2.join();
return proc.waitFor();
} finally {
proc.destroy();
}
}
@Override
public InputStream getStdout() {
throw new UnsupportedOperationException();
}
@Override
public InputStream getStderr() {
throw new UnsupportedOperationException();
}
@Override
public OutputStream getStdin() {
throw new UnsupportedOperationException();
}
};
}
public Channel launchChannel(String[] cmd, OutputStream out, FilePath _workDir, Map<String, String> envVars) throws IOException, InterruptedException {
printCommandLine(cmd, _workDir);
try {
Process proc = launcher.launch(Util.join(asList(cmd), " "), _workDir.getRemote());
return new Channel("channel over named pipe to "+launcher.getHostName(),
Computer.threadPoolForRemoting, proc.getInputStream(), new BufferedOutputStream(proc.getOutputStream()));
} catch (JIException e) {
throw new IOException(e);
}
}
public void kill(Map<String, String> modelEnvVars) throws IOException, InterruptedException {
// no way to do this
}
}
......@@ -46,7 +46,6 @@ import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.listeners.ItemListener;
import hudson.tasks.BuildTrigger.DescriptorImpl.ItemListenerImpl;
import hudson.util.FormValidation;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
......@@ -192,6 +191,7 @@ public class BuildTrigger extends Recorder implements DependencyDeclarer {
public static boolean execute(AbstractBuild build, BuildListener listener) {
PrintStream logger = listener.getLogger();
// Check all downstream Project of the project, not just those defined by BuildTrigger
// TODO this may not yet be up to date if rebuildDependencyGraphAsync has been used; need a method to wait for the last call made before now to finish
final DependencyGraph graph = Jenkins.getInstance().getDependencyGraph();
List<Dependency> downstreamProjects = new ArrayList<Dependency>(
graph.getDownstreamDependencies(build.getProject()));
......@@ -242,11 +242,8 @@ public class BuildTrigger extends Recorder implements DependencyDeclarer {
return true;
}
/**
* Called from {@link ItemListenerImpl} when a job is renamed.
*
* @return true if this {@link BuildTrigger} is changed and needs to be saved.
*/
/** @deprecated Does not handle folder moves. */
@Deprecated
public boolean onJobRenamed(String oldName, String newName) {
// quick test
if(!childProjects.contains(oldName))
......@@ -354,17 +351,19 @@ public class BuildTrigger extends Recorder implements DependencyDeclarer {
@Extension
public static class ItemListenerImpl extends ItemListener {
@Override
public void onRenamed(Item item, String oldName, String newName) {
public void onLocationChanged(Item item, String oldFullName, String newFullName) {
// update BuildTrigger of other projects that point to this object.
// can't we generalize this?
for( Project<?,?> p : Jenkins.getInstance().getAllItems(Project.class) ) {
BuildTrigger t = p.getPublishersList().get(BuildTrigger.class);
if(t!=null) {
if(t.onJobRenamed(oldName,newName)) {
String cp2 = Items.computeRelativeNamesAfterRenaming(oldFullName, newFullName, t.childProjects, p.getParent());
if (!cp2.equals(t.childProjects)) {
t.childProjects = cp2;
try {
p.save();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to persist project setting during rename from "+oldName+" to "+newName,e);
LOGGER.log(Level.WARNING, "Failed to persist project setting during rename from "+oldFullName+" to "+newFullName,e);
}
}
}
......
......@@ -133,6 +133,7 @@ public class JUnitResultArchiver extends Recorder implements MatrixAggregatable
TestResult result = parse(testResults, build, launcher, listener);
try {
// TODO can the build argument be omitted now, or is it used prior to the call to addAction?
action = new TestResultAction(build, result, listener);
} catch (NullPointerException npe) {
throw new AbortException(Messages.JUnitResultArchiver_BadXML(testResults));
......@@ -173,7 +174,7 @@ public class JUnitResultArchiver extends Recorder implements MatrixAggregatable
return true;
}
build.getActions().add(action);
build.addAction(action);
CHECKPOINT.report();
if (action.getResult().getFailCount() > 0)
......
......@@ -62,11 +62,17 @@ public class TestResultAction extends AbstractTestResultAction<TestResultAction>
private Integer totalCount;
private List<Data> testData = new ArrayList<Data>();
@Deprecated
public TestResultAction(AbstractBuild owner, TestResult result, BuildListener listener) {
super(owner);
setResult(result, listener);
}
/** @since 1.545 */
public TestResultAction(TestResult result, BuildListener listener) {
this(null, result, listener);
}
/**
* Overwrites the {@link TestResult} by a new data set.
*/
......
......@@ -28,6 +28,14 @@ import hudson.model.*;
import hudson.tasks.junit.CaseResult;
import hudson.util.*;
import hudson.util.ChartUtil.NumberOnlyBuildLabel;
import java.awt.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import jenkins.model.RunAction2;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
......@@ -44,13 +52,6 @@ import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import java.awt.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Common base class for recording test result.
*
......@@ -61,15 +62,28 @@ import java.util.concurrent.ConcurrentHashMap;
* @author Kohsuke Kawaguchi
*/
@ExportedBean
public abstract class AbstractTestResultAction<T extends AbstractTestResultAction> implements HealthReportingAction {
public final AbstractBuild<?,?> owner;
public abstract class AbstractTestResultAction<T extends AbstractTestResultAction> implements HealthReportingAction, RunAction2 {
public transient AbstractBuild<?,?> owner;
private Map<String,String> descriptions = new ConcurrentHashMap<String, String>();
/** @since 1.545 */
protected AbstractTestResultAction() {}
/** @deprecated Use the default constructor and just call {@link Run#addAction} to associate the build with the action. */
@Deprecated
protected AbstractTestResultAction(AbstractBuild owner) {
this.owner = owner;
}
@Override public void onAttached(Run<?, ?> r) {
this.owner = (AbstractBuild<?,?>) r;
}
@Override public void onLoad(Run<?, ?> r) {
this.owner = (AbstractBuild<?,?>) r;
}
/**
* Gets the number of failed tests.
*/
......
......@@ -67,10 +67,14 @@ public abstract class AggregatedTestResultAction extends AbstractTestResultActio
*/
public final List<Child> children = new ArrayList<Child>();
@Deprecated
public AggregatedTestResultAction(AbstractBuild owner) {
super(owner);
}
/** @since 1.545 */
public AggregatedTestResultAction() {}
protected void update(List<? extends AbstractTestResultAction> children) {
failCount = skipCount = totalCount = 0;
this.children.clear();
......
......@@ -87,7 +87,7 @@ public class AggregatedTestResultPublisher extends Recorder {
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
// add a TestResult just so that it can show up later.
build.addAction(new TestResultAction(jobs,includeFailedBuilds,build));
build.addAction(new TestResultAction(jobs, includeFailedBuilds, build));
return true;
}
......@@ -131,6 +131,7 @@ public class AggregatedTestResultPublisher extends Recorder {
private transient List<AbstractProject> didntRun;
private transient List<AbstractProject> noFingerprints;
@SuppressWarnings("deprecation") // calls getProject in constructor, so needs owner immediately
public TestResultAction(String jobs, boolean includeFailedBuilds, AbstractBuild<?,?> owner) {
super(owner);
this.includeFailedBuilds = includeFailedBuilds;
......
......@@ -38,10 +38,15 @@ import hudson.model.Action;
* @author Kohsuke Kawaguchi
*/
public class MatrixTestResult extends AggregatedTestResultAction {
@Deprecated
public MatrixTestResult(MatrixBuild owner) {
super(owner);
}
/** @since 1.545 */
public MatrixTestResult() {}
/**
* Use the configuration name.
*/
......
......@@ -46,7 +46,7 @@ public class TestResultAggregator extends MatrixAggregator {
@Override
public boolean startBuild() throws InterruptedException, IOException {
result = new MatrixTestResult(build);
result = new MatrixTestResult();
build.addAction(result);
return true;
}
......
......@@ -74,6 +74,12 @@ import jenkins.model.RunAction2;
/**
* {@link Trigger} that checks for SCM updates periodically.
*
* You can add UI elements under the SCM section by creating a
* config.jelly or config.groovy in the resources area for
* your class that inherits from SCMTrigger and has the
* @{@link hudson.model.Extension} annotation. The UI should
* be wrapped in an f:section element to denote it.
*
* @author Kohsuke Kawaguchi
*/
public class SCMTrigger extends Trigger<SCMedItem> {
......
......@@ -58,6 +58,7 @@ import java.util.logging.Logger;
import antlr.ANTLRException;
import javax.annotation.CheckForNull;
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import hudson.model.Items;
/**
* Triggers a {@link Build}.
......@@ -78,6 +79,7 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
* @param newInstance
* True if this may be a newly created trigger first attached to the {@link Project} (generally if the project is being created or configured).
* False if this is invoked for a {@link Project} loaded from disk.
* @see Items#currentlyUpdatingByXml
*/
public void start(J project, boolean newInstance) {
this.job = project;
......
......@@ -23,7 +23,7 @@
*/
package hudson.util;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
......@@ -38,8 +38,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Arrays;
import static java.util.logging.Level.FINE;
import java.util.logging.Logger;
/**
......@@ -192,11 +190,9 @@ public class CopyOnWriteList<E> implements Iterable<E> {
try {
Object item = readItem(reader, context, items);
items.add(item);
} catch (CannotResolveClassException e) {
LOGGER.log(FINE, "Failed to resolve class", e);
} catch (XStreamException e) {
RobustReflectionConverter.addErrorInContext(context, e);
} catch (LinkageError e) {
LOGGER.log(FINE, "Failed to resolve class", e);
RobustReflectionConverter.addErrorInContext(context, e);
}
reader.moveUp();
......@@ -206,5 +202,4 @@ public class CopyOnWriteList<E> implements Iterable<E> {
}
}
private static final Logger LOGGER = Logger.getLogger(CopyOnWriteList.class.getName());
}
......@@ -23,7 +23,6 @@
*/
package hudson.util;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
......@@ -31,16 +30,15 @@ import com.thoughtworks.xstream.converters.reflection.SerializableConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import static java.util.logging.Level.FINE;
import java.util.logging.Logger;
/**
* {@link CollectionConverter} that ignores {@link CannotResolveClassException}.
* {@link CollectionConverter} that ignores {@link XStreamException}.
*
* <p>
* This allows Hudson to load XML files that contain non-existent classes
......@@ -84,16 +82,13 @@ public class RobustCollectionConverter extends CollectionConverter {
try {
Object item = readItem(reader, context, collection);
collection.add(item);
} catch (CannotResolveClassException e) {
LOGGER.log(FINE, "Failed to resolve class", e);
} catch (XStreamException e) {
RobustReflectionConverter.addErrorInContext(context, e);
} catch (LinkageError e) {
LOGGER.log(FINE, "Failed to resolve class", e);
RobustReflectionConverter.addErrorInContext(context, e);
}
reader.moveUp();
}
}
private static final Logger LOGGER = Logger.getLogger(RobustCollectionConverter.class.getName());
}
......@@ -23,12 +23,12 @@
*/
package hudson.util;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.reflection.MissingFieldException;
import com.thoughtworks.xstream.converters.reflection.ObjectAccessException;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.ReflectionConverter;
......@@ -38,7 +38,6 @@ import com.thoughtworks.xstream.core.util.Primitives;
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.mapper.Mapper;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.Saveable;
......@@ -293,14 +292,9 @@ public class RobustReflectionConverter implements Converter {
implicitCollectionsForCurrentObject = writeValueToImplicitCollection(context, value, implicitCollectionsForCurrentObject, result, fieldName);
}
}
} catch (MissingFieldException e) {
LOGGER.log(FINE, "Skipping a non-existent field " + e.getFieldName(), e);
addErrorInContext(context, e);
} catch (CannotResolveClassException e) {
LOGGER.log(FINE, "Skipping a non-existent type", e);
} catch (XStreamException e) {
addErrorInContext(context, e);
} catch (LinkageError e) {
LOGGER.log(FINE, "Failed to resolve a type", e);
addErrorInContext(context, e);
}
......@@ -316,6 +310,7 @@ public class RobustReflectionConverter implements Converter {
}
public static void addErrorInContext(UnmarshallingContext context, Throwable e) {
LOGGER.log(FINE, "Failed to load", e);
ArrayList<Throwable> list = (ArrayList<Throwable>)context.get("ReadError");
if (list == null)
context.put("ReadError", list = new ArrayList<Throwable>());
......
......@@ -26,12 +26,12 @@ package hudson.util.xstream;
import com.google.common.collect.ImmutableList;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.CollectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.SerializableConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.mapper.Mapper;
import hudson.util.RobustReflectionConverter;
......@@ -76,7 +76,7 @@ public class ImmutableListConverter extends CollectionConverter {
try {
Object item = readItem(reader, context, items);
items.add(item);
} catch (CannotResolveClassException e) {
} catch (XStreamException e) {
RobustReflectionConverter.addErrorInContext(context, e);
} catch (LinkageError e) {
RobustReflectionConverter.addErrorInContext(context, e);
......
/*
* The MIT License
*
* Copyright 2013 Jesse Glick.
*
* 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.model.Item;
import hudson.model.TopLevelItem;
import hudson.model.listeners.ItemListener;
import java.io.IOException;
/**
* Item group which supports items being directly moved in or out of it.
* @since 1.548
*/
public interface DirectlyModifiableTopLevelItemGroup extends ModifiableTopLevelItemGroup {
/**
* Returns true if a particular item may be added to this group.
* @param item an item currently elsewhere
* @return true if {@link #add} may be called with this item
*/
boolean canAdd(TopLevelItem item);
/**
* Adds an item to this group.
* Unlike {@link Jenkins#putItem} this does not try to call {@link Item#delete} on an existing item, nor does it fire {@link ItemListener#onCreated}, nor check permissions.
* Normally you would call {@link Item#onLoad} after calling this method (the implementation is not expected to do so).
* @param <I> the kind of item
* @param item an item to add which is currently elsewhere
* @param name the desired item name in this group (might simply be the original {@link Item#getName})
* @return normally the same {@code item}, but might be a new cppy if necessary
* @throws IOException if adding fails
* @throws IllegalArgumentException if {@link #canAdd} is false, or an item with this name already exists, or this item is as yet unnamed
*/
<I extends TopLevelItem> I add(I item, String name) throws IOException, IllegalArgumentException;
/**
* Removes an item from this group.
* Unlike {@link #onDeleted} this is not expected to fire any events.
* @param item an item which was part of this group
* @throws IOException if removing fails
* @throws IllegalArgumentException if this was not part of the group to begin with
*/
void remove(TopLevelItem item) throws IOException, IllegalArgumentException;
}
......@@ -56,6 +56,7 @@ import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.ItemGroupMixIn;
import hudson.model.Items;
import hudson.model.ModifiableViewGroup;
import hudson.model.JDK;
import hudson.model.Job;
import hudson.model.JobPropertyDescriptor;
......@@ -78,7 +79,6 @@ import hudson.model.UnprotectedRootAction;
import hudson.model.UpdateCenter;
import hudson.model.User;
import hudson.model.View;
import hudson.model.ViewGroup;
import hudson.model.ViewGroupMixIn;
import hudson.model.Descriptor.FormException;
import hudson.model.labels.LabelAtom;
......@@ -289,6 +289,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import static java.util.logging.Level.SEVERE;
import java.util.logging.LogRecord;
......@@ -304,8 +305,8 @@ import javax.annotation.Nullable;
* @author Kohsuke Kawaguchi
*/
@ExportedBean
public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGroup, StaplerProxy, StaplerFallback,
ViewGroup, AccessControlled, DescriptorByNameOwner,
public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLevelItemGroup, StaplerProxy, StaplerFallback,
ModifiableViewGroup, AccessControlled, DescriptorByNameOwner,
ModelObjectWithContextMenu, ModelObjectWithChildren {
private transient final Queue queue;
......@@ -434,6 +435,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
private List<JDK> jdks = new ArrayList<JDK>();
private transient volatile DependencyGraph dependencyGraph;
private final transient AtomicBoolean dependencyGraphDirty = new AtomicBoolean();
/**
* Currently active Views tab bar.
......@@ -472,7 +474,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
* Active {@link Cloud}s.
*/
public final Hudson.CloudList clouds = new Hudson.CloudList(this);
public static class CloudList extends DescribableList<Cloud,Descriptor<Cloud>> {
public CloudList(Jenkins h) {
super(h);
......@@ -1456,6 +1458,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
return viewGroupMixIn.getViews();
}
@Override
public void addView(View v) throws IOException {
viewGroupMixIn.addView(v);
}
......@@ -2433,6 +2436,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
items.remove(oldName);
items.put(newName,job);
// For compatibility with old views:
for (View v : views)
v.onJobRenamed(job, oldName, newName);
save();
......@@ -2442,15 +2446,31 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
* Called in response to {@link Job#doDoDelete(StaplerRequest, StaplerResponse)}
*/
public void onDeleted(TopLevelItem item) throws IOException {
for (ItemListener l : ItemListener.all())
l.onDeleted(item);
ItemListener.fireOnDeleted(item);
items.remove(item.getName());
// For compatibility with old views:
for (View v : views)
v.onJobRenamed(item, item.getName(), null);
save();
}
@Override public boolean canAdd(TopLevelItem item) {
return true;
}
@Override synchronized public <I extends TopLevelItem> I add(I item, String name) throws IOException, IllegalArgumentException {
if (items.containsKey(name)) {
throw new IllegalArgumentException("already an item '" + name + "'");
}
items.put(name, item);
return item;
}
@Override public void remove(TopLevelItem item) throws IOException, IllegalArgumentException {
items.remove(item.getName());
}
public FingerprintMap getFingerprintMap() {
return fingerprintMap;
}
......@@ -3608,6 +3628,7 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
// volatile acts a as a memory barrier here and therefore guarantees
// that graph is fully build, before it's visible to other threads
dependencyGraph = graph;
dependencyGraphDirty.set(false);
}
/**
......@@ -3620,13 +3641,16 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
* @since 1.522
*/
public Future<DependencyGraph> rebuildDependencyGraphAsync() {
return MasterComputer.threadPoolForRemoting.submit(new java.util.concurrent.Callable<DependencyGraph>() {
dependencyGraphDirty.set(true);
return Timer.get().schedule(new java.util.concurrent.Callable<DependencyGraph>() {
@Override
public DependencyGraph call() throws Exception {
rebuildDependencyGraph();
if (dependencyGraphDirty.get()) {
rebuildDependencyGraph();
}
return dependencyGraph;
}
});
}, 500, TimeUnit.MILLISECONDS);
}
public DependencyGraph getDependencyGraph() {
......
......@@ -26,18 +26,14 @@ package jenkins.model.lazy;
import hudson.model.Job;
import hudson.model.Run;
import hudson.model.RunMap;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
......@@ -49,6 +45,9 @@ import javax.annotation.CheckForNull;
import static jenkins.model.lazy.AbstractLazyLoadRunMap.Direction.*;
import static jenkins.model.lazy.Boundary.*;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* {@link SortedMap} that keeps build records by their build numbers, in the descending order
......@@ -210,6 +209,16 @@ public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> i
return dir != null;
}
/**
* Updates base directory location after directory changes.
* This method should be used on jobs renaming, etc.
* @param dir Directory location
* @since 1.546
*/
public final void updateBaseDir(File dir) {
this.dir = dir;
}
/**
* Let go of all the loaded references.
*
......@@ -219,30 +228,32 @@ public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer,R> i
*/
public void purgeCache() {
index = new Index();
fullyLoaded = false;
loadIdOnDisk();
}
private void loadIdOnDisk() {
String[] buildDirs = dir.list(createDirectoryFilter());
if (buildDirs==null) {
String[] kids = dir.list();
if (kids == null) {
// the job may have just been created
buildDirs=EMPTY_STRING_ARRAY;
kids = EMPTY_STRING_ARRAY;
}
// wrap into ArrayList to enable mutation
Arrays.sort(buildDirs);
idOnDisk = new SortedList<String>(new ArrayList<String>(Arrays.asList(buildDirs)));
// TODO: should we check that shortcuts is a symlink?
String[] shortcuts = dir.list();
if (shortcuts==null) shortcuts=EMPTY_STRING_ARRAY;
SortedIntList list = new SortedIntList(shortcuts.length/2);
for (String s : shortcuts) {
try {
list.add(Integer.parseInt(s));
} catch (NumberFormatException e) {
// this isn't a shortcut
List<String> buildDirs = new ArrayList<String>();
FilenameFilter buildDirFilter = createDirectoryFilter();
SortedIntList list = new SortedIntList(kids.length / 2);
for (String s : kids) {
if (buildDirFilter.accept(dir, s)) {
buildDirs.add(s);
} else {
try {
list.add(Integer.parseInt(s));
} catch (NumberFormatException e) {
// this isn't a shortcut
}
}
}
Collections.sort(buildDirs);
idOnDisk = new SortedList<String>(buildDirs);
list.sort();
numberOnDisk = list;
}
......
......@@ -20,6 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
FilePath.did_not_manage_to_validate_may_be_too_sl=Impossible de valider {0} (peut-\u00eatre est-ce trop lent)
FilePath.validateAntFileMask.whitespaceSeprator=\
Les espaces ne peuvent plus \u00eatre utilis\u00e9s comme s\u00e9parateurs. Merci d''utiliser maintenant '','' comme s\u00e9parateur \u00e0 la place.
FilePath.validateAntFileMask.doesntMatchAndSuggest=\
......@@ -27,7 +28,7 @@ FilePath.validateAntFileMask.doesntMatchAndSuggest=\
FilePath.validateAntFileMask.portionMatchAndSuggest=''{0}'' ne correspond \u00e0 rien, m\u00eame si ''{1}'' existe
FilePath.validateAntFileMask.portionMatchButPreviousNotMatchAndSuggest=''{0}'' ne correspond \u00e0 rien : ''{1}'' existe mais pas ''{2}''
FilePath.validateAntFileMask.doesntMatchAnything=''{0}'' ne correspond \u00e0 rien
FilePath.validateAntFileMask.doesntMatchAnythingAndSuggest=''{0}'' ne correspond \u00e0 rien : m\u00eame ''{1}'' n'existe pas
FilePath.validateAntFileMask.doesntMatchAnythingAndSuggest=''{0}'' ne correspond \u00e0 rien : m\u00eame ''{1}'' n''existe pas
FilePath.validateRelativePath.wildcardNotAllowed=L''utilisation des Wildcard n''est pas autoris\u00e9e ici
FilePath.validateRelativePath.notFile=''{0}'' n''est pas un fichier
......@@ -35,6 +36,8 @@ FilePath.validateRelativePath.notDirectory=''{0}'' n''est pas un r\u00e9pertoire
FilePath.validateRelativePath.noSuchFile=Aucun fichier correspondant : ''{0}''
FilePath.validateRelativePath.noSuchDirectory=Aucun r\u00e9pertoire correspondant : ''{0}''
PluginManager.PluginDoesntSupportDynamicLoad.RestartRequired=Le plugin {0} ne supporte pas le chargement dynamique. Jenkins doit \u00eatre red\u00e9marr\u00e9 pour que la mise \u00e0 jour soit effective.
PluginManager.PluginIsAlreadyInstalled.RestartRequired=Le plugin {0} est d\u00e9j\u00e0 install\u00e9. Jenkins doit \u00eatre red\u00e9marr\u00e9 pour que la mise \u00e0 jour soit effective.
Util.millisecond={0} ms
Util.second={0} s
Util.minute={0} mn
......@@ -52,6 +55,16 @@ FilePath.TildaDoesntWork=''~'' n''est support\u00e9 que sur les shells Unix.
PluginManager.DisplayName=Gestion des plugins
PluginManager.PortNotANumber=Le port n''est pas un nombre
PluginManager.PortNotInRange=Le port n''est pas dans l''intervalle de {0} \u00e0 {1}
PluginManager.UploadPluginsPermission.Description=\
La permission "upload plugin" autorise un utilisateur \u00e0 uploader des plugins.
PluginManager.ConfigureUpdateCenterPermission.Description=\
La permission "configure update center" autorise un utilisateur \u00e0 \
configurer les sites de mise \u00e0 jour et le param\u00e9trage du proxy.
AboutJenkins.DisplayName=A propos de Jenkins
AboutJenkins.Description=Afficher les informations de version et de licence
ProxyConfiguration.TestUrlRequired=Une URL de test est requise.
ProxyConfiguration.FailedToConnectViaProxy=Impossible de se connecter \u00e0 {0}.
ProxyConfiguration.FailedToConnect=Impossible de se connecter \u00e0 {0} (code {1}).
ProxyConfiguration.Success=Succ\u00e8s
......@@ -24,13 +24,13 @@ HTTP\ Proxy\ Configuration=Configuration du proxy HTTP
Submit=Soumettre
Upload\ Plugin=Soumettre un plugin
File=Fichier
Update\ Site=Rafra\u00EEchir site
Update\ Site=Site de mise \u00E0 jour
Upload=Soumettre
lastUpdated=Derni\u00E8re mise \u00E0 jour\u00A0: il y a {0}
Check\ now=Vérifier maintenant
Check\ now=V\u00E9rifier maintenant
uploadtext=Vous pouvez t\u00E9l\u00E9verser un fichier .hpi pour installer un plugin ext\u00E9rieur au d\u00E9p\u00F4t centralis\u00E9 de plugin.
Proxy\ Needs\ Authorization=Le proxy n\u00E9cessite une authentification
Server=Serveur
User\ name=Nom d''utilisateur
No\ Proxy\ for=Pas de proxy pour
No\ Proxy\ Host=Pas de proxy pour
Password=Mot de passe
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
# About {0}
about=Sobre
No\ information\ recorded=Sem informa\u00e7\u00e3o registrada
3rd\ Party\ Dependencies=Depend\u00eancia de terceiros
\ No newline at end of file
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
JENKINS_HOME\ is\ almost\ full=o JENKINS_HOME est\u00e1 quase cheio
description.2=Para previnir esse problema, fa\u00e7a alguma coisa agora.
description.1=O seu <tt>JENKINS_HOME</tt> ({0}) est\u00e1 quase cheio. \
Quando esse diret\u00f3rio estiver lotado ocorrer\u00e3o alguns estragos, pois o Jenkins n\u00e3o pode gravar mais dado nenhum.
solution.2=Mova o <tt>JENKINS_HOME</tt> para uma parti\u00e7\u00e3o maior. \
Veja <a href="http://wiki.jenkins-ci.org/display/JENKINS/Administering+Jenkins">a nossa Wiki</a> para aprender como fazer isso.
blurb=<tt>JENKINS_HOME</tt> est\u00e1 quase cheio
solution.1=Limpe alguns arquivos dessa parti\u00e7\u00e3o para liberar mais espa\u00e7o.
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Dismiss=Dispensar
blurb=Seu diret\u00f3rio de dados do Jenkins "{0}" (conhecido como <tt>JENKINS_HOME</tt>) est\u00e1 quase cheio. Voc\u00ea deve fazer alguma coisa antes que ele fique completamente cheio.
Tell\ me\ more=Mais detalhes
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Short=Curto
Timespan=intervalo de tempo
JVM\ Memory\ Usage=Uso de mem\u00f3ria da JVM
Medium=M\u00e9dio
Long=Longo
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
MemoryUsageMonitor.USED=Usado
MemoryUsageMonitor.TOTAL=Total
OldDataMonitor.DisplayName=Gerenciar dados antigos
HudsonHomeDiskUsageMonitor.DisplayName=Monitor de uso de disco
OldDataMonitor.Description=Limpar arquivos de configura\u00e7\u00f5es de plugins antigos e vers\u00f5es anteriores.
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
# Descriptor {0} from plugin {2} with display name {1}
problem=
# The following extensions have no ID value and therefore likely cause a problem. Please upgrade these plugins if they are not the latest, \
# and if they are the latest, please file a bug so that we can fix them.
blurb=
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Type=Tipo
blurb.6=\u00c9 aceit\u00e1vel deixar esses dados ileg\u00edveis nesses arquivos,o Jenkins vai ignor\u00e1-los. \
Para evitar essas mensagens no log de startup do Jenkins, voc\u00ea pode remover esses dados regravando os arquivos usando o bot\u00e3o abaixo.
Discard\ Unreadable\ Data=Descartar dados ileg\u00edveis
blurb.4=Eventualmente o c\u00f3digo que suporta essas migra\u00e7\u00f5es de dados pode ser removido. A compatibilidade ser\u00e1 \
mantida por pelo menos 150 releases antes de uma mudan\u00e7a de estrutura. As vers\u00f5es mais antigas que essa \
em negrito abaixo, \u00e9 recomendado que regrave esses arquivos.
Version=Vers\u00e3o
Upgrade=Upgrade
blurb.5=(downgrade assim que for poss\u00edvel com a vers\u00e3o selecionada)
Resave\ data\ files\ with\ structure\ changes\ no\ newer\ than\ Jenkins=Regravar os arquivos de dados com a mudan\u00e7a de estrutura sem ser mais nova que o Jenkins
blurb.2=Algumas vezes ocorre erro ao ler os dados (se o plugin adiciona algum dado que depois \u00e9 \
desativado, se o c\u00f3digo de migra\u00e7\u00e3o n\u00e3o estiver escrito com as mudan\u00e7as de estrutura, ou se o Jenkins sofreu \
downgraded depois de tiver escrito algum dado que \u00e9 ileg\u00edvel por uma vers\u00e3o mais antiga). \
Esses erros s\u00e3o logados,mas o dado ileg\u00edvel ser\u00e1 ignorado, permitindo ao Jenkins iniciar e \
funcionar corretamente.
Error=Erro
Unreadable\ Data=Dado ileg\u00edvel
blurb.1=Quando existirem mudan\u00e7as em como o dado \u00e9 armazenado no disco, o Jenkins usa a seguinte estrat\u00e9gia: \
o dado \u00e9 migrado para a nova estrutura quando for carregado, mas o arquivo n\u00e3o \u00e9 regravado no novo formato. \
Isso permite um downgrade do Jenkins se necess\u00e1rio, entretando pode tamb\u00e9m deixar dados no disco em formato \
antigo por tempo indeterminado. A tabela abaixo lista os arquivos que cont\u00e9m esses dados, \
as vers\u00f5es do Jenkins e quando a estrutura de dados foi alterada.
No\ old\ data\ was\ found.=Nenhum dado antigo foi encontrado.
blurb.3=O formul\u00e1rio abaixo pode ser usado para regravar os arquivos no formato atual. Fazer isso significa \
fazer um downgrade para uma vers\u00e3o do Jenkins mais antiga do que a selecionada,ele n\u00e3o conseguir\u00e1 ler os dados \
no novo formato. Note que simplesmemnte usando o Jenkins para criar e configurar jobs \
e rodar builds pode gravar dados que n\u00e3o ser\u00e3o lidos por vers\u00f5es antigas do Jenkins, mesmo quando \
esse formul\u00e1rio n\u00e3o for usado. Se algum dado ileg\u00edvel der erro no lado direito da tabela \
abaixo, esse dado ser\u00e1 perdido quando o arquivo for regravado.
Name=Nome
Manage\ Old\ Data=Gerenciar dado antigo
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
You\ have\ data\ stored\ in\ an\ older\ format\ and/or\ unreadable\ data.=Voc\u00ea tem dados armazenados em um formato antigo e/ou ileg\u00edvel.
Dismiss=Desconsiderar
Manage=Gerenciar
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Dismiss=
More\ Info=
# It appears that your reverse proxy set up is broken.
blurb=
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
GroovyInitScript.init=Executar um script init definido pelo usu\u00e1rio
InitialUserContent.init=Preparando o conte\u00fado inicial
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Log\ level=N\u00edvel de log
Logger=Logger
Save=Gravar
Loggers=Loggers
List\ of\ loggers\ and\ the\ log\ levels\ to\ record=Lista de loggers e seus n\u00edveis de log
Name=Nome
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Are\ you\ sure\ about\ deleting\ this\ log\ recorder?=Tem certeza que deseja remover esse registro de log?
Yes=Sim
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Back\ to\ Loggers=Voltar aos loggers
Delete=Remover
Log\ records=Registros de log
Configure=Configurar
......@@ -20,5 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Password=Contraseña
Administrator\ user\ name=Nombre del usuario administrador
Jenkins\ Log=Log do Jenkins
# The MIT License
#
# Copyright 2012 Seiji Sogabe
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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,5 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Administrator\ user\ name=\u7ba1\u7406\u8005\u306e\u30e6\u30fc\u30b6\u30fc\u540d
Password=\u30d1\u30b9\u30ef\u30fc\u30c9
>\ SEVERE=>\ SEVERE
>\ WARNING=>\ WARNING
All=Tudo
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
All\ Jenkins\ Logs=Todos os logs do Jenkins
Log\ Recorders=Registros de log
Log=Log
Add\ new\ log\ recorder=Adicionar novo registro de log
Name=Nome
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Adjust\ Levels=Ajustar n\u00edveis
url=http://wiki.jenkins-ci.org//x/YYI5Ag
Submit=Enviar
Logger\ Configuration=Configura\u00e7\u00e3o de logger
defaultLoggerMsg=Um logger sem nome ser\u00e1 o logger padr\u00e3o. Esse n\u00edvel ser\u00e1 herdado por todos os loggers sem um n\u00edvel configurado.
Level=N\u00edvel
Name=Nome
# The MIT License
#
# Copyright (c) 2004-2010, Sun Microsystems, Inc. Kohsuke Kawaguchi. Knud Poulsen.
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
blurb=\
Name=Nome
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Manage\ Jenkins=Gerenciar Jenkins
Logger\ List=Lista de logger
Log\ Levels=N\u00edveis de log
All\ Logs=Todos os logs
New\ Log\ Recorder=Novo registro de log
Back\ to\ Dashboard=Voltar ao painel principal
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
LogRecorderManager.DisplayName=log
LogRecorderManager.init=Inicializando registros de log
# The MIT License
#
# Copyright (c) 2013, Chunghwa Telecom Co., Ltd., Pei-Tang Huang
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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,5 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Administrator\ user\ name=\u7cfb\u7d71\u7ba1\u7406\u54e1\u4f7f\u7528\u8005\u540d\u7a31
Password=\u5bc6\u78bc
Node/Label=N\u00f3
Labels=Label
Individual\ nodes=N\u00f3s individuais
Name=Nome
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Label\ Expressions=Express\u00f5es
Name=Nome
# The MIT License
#
# Copyright (c) 2013, Chunghwa Telecom Co., Ltd., Pei-Tang Huang
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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,5 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
User\ name=\u4f7f\u7528\u8005\u540d\u7a31
Password=\u5bc6\u78bc
Not\ run=N\u00e3o executado
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
cannotMsg=N\u00e3o foi poss\u00edvel remover esse build: {0}
Are\ you\ sure\ about\ deleting\ the\ build\ and\ all\ configurations\ in\ this\ build?=Tem certeza que deseja remover esse build e todas suas configura\u00e7\u00f5es ?
Yes=Sim
Warning=Aviso
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Delete\ Build=Remover build
Delete\ this\ build\ and\ all\ configurations\ in\ this\ build=Remover esse build e todas suas configura\u00e7\u00f5es
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Not\ configured=Non configuree
Not\ configured=Non configur\u00E9e
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Not\ configured=N\u00e3o configurado
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Advanced\ Project\ Options=Op\u00e7\u00f5es avan\u00e7adas de projeto
Directory=Diret\u00f3rio
Filter=Filtro
Directory\ for\ sub-builds=Diret\u00f3rio dos sub-builds
Display\ Name=Nome de exibi\u00e7\u00e3o
Use\ custom\ workspace=Usar workspace customizado
Combination\ Filter=Filtro combinado
Execution\ Strategy=Estrat\u00e9gia de execu\u00e7\u00e3o
Configuration\ Matrix=Configura\u00e7\u00e3o da matriz
Add\ axis=Adicionar eixo
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Project\ name=Nome do projeto
Latest\ Test\ Result=\u00daltimo resultado de teste
Project=Projeto
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
# \
# Suitable for projects that need a large number of different configurations, \
# such as testing on multiple environments, platform-specific builds, etc.
body=
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
MatrixBuild.Completed={0} completado com resultado {1}
MatrixRun.KeptBecauseOfParent=Mantido porque {0} ser\u00e1 mantido
TextArea.DisplayName=Eixo definido pelo usu\u00e1rio
MatrixProject.DuplicateAxisName=Nome do eixo duplicado
MatrixBuild.Triggering=Disparando {0}
LabelAxis.DisplayName=Slaves
JDKAxis.DisplayName=JDK
MatrixBuild.Interrupting=Interrompendo {0}
MatrixBuild.depends_on_this={0} depended disso.
LabelExpAxis.DisplayName=Label
MatrixBuild.AppearsCancelled= {0} parece estar cancelado
MatrixConfiguration.Pronoun=Configura\u00e7\u00e3o
MatrixProject.Pronoun=Projeto com multi-configura\u00e7\u00f5es
MatrixProject.DisplayName=Construir Build projeto com multi-configura\u00e7\u00f5es
MatrixBuild.Cancelled={0} cancelado
# The MIT License
#
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Reginaldo L. Russinholi, Cleiber Silva
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Reginaldo L. Russinholi, Cleiber Silva,
# Bruno Meneguello
#
# 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,14 +21,22 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
MatrixBuild.depends_on_this={0} depende deste.
MatrixProject.DisplayName=Construir projeto de m\u00faltiplas configura\u00e7\u00f5es
MatrixProject.Pronoun=Projeto de M\u00faltiplas Configura\u00e7\u00f5es
MatrixBuild.Triggering=Disparando {0}
MatrixBuild.AppearsCancelled={0} parece estar cancelado
MatrixBuild.Cancelled=Cancelado {0}
MatrixBuild.Interrupting=Interrompendo {0}
MatrixBuild.Completed={0} completado com o resultado {1}
MatrixConfiguration.Pronoun=Configura\u00e7\u00e3o
MatrixRun.KeptBecauseOfParent=Mantido porque {0} est\u00e1 mantido
MatrixConfiguration.Pronoun=Configura\u00e7\u00e3o# mantida porque {0} est\u00e1 mantida
MatrixRun.KeptBecauseOfParent=
# Duplicate axis name
MatrixProject.DuplicateAxisName=Duplicar nome do eixo
JDKAxis.DisplayName=JDK
LabelAxis.DisplayName=Slaves
LabelExpAxis.DisplayName=Express\u00e7o de R\u00f3tulo
TextArea.DisplayName=Eixo Definido pelo Usu\u00e1rio
# The MIT License
#
# Copyright (c) 2013, Chunghwa Telecom Co., Ltd., Pei-Tang Huang
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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,5 +20,5 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
User\ name=\u4f7f\u7528\u8005\u540d\u7a31
Password=\u5bc6\u78bc
Values=Valores
Name=Nome
......@@ -21,9 +21,7 @@
# THE SOFTWARE.
Advanced\ Project\ Options=Options avanc\u00E9es du projet
Restrict\ where\ this\ project\ can\ be\ run=Restreindre o\u00F9 le projet peut \u00EAtre ex\u00E9cuter
Tie\ this\ project\ to\ a\ node=Associer ce projet \u00E0 un noeud
Node=Noeud
Execute\ concurrent\ builds\ if\ necessary\ =Ex\u00E9cuter les builds en parall\u00E8le si n\u00E9cessaire
JDK\ to\ be\ used\ for\ this\ project=Le JDK \u00E0 utiliser pour ce projet
default.value=(Valeur par d\u00E9faut)
......@@ -22,4 +22,4 @@
Are\ you\ sure\ about\ deleting\ the\ job?=Etes-vous sûr de vouloir supprimer ce job?
Yes=Oui
blurb=\u00CAtes vous s\u00FBr de vouloir supprimer ce {0} "{1}"?
blurb=\u00CAtes-vous s\u00FBr de vouloir supprimer ce {0} "{1}"?
\ No newline at end of file
......@@ -182,6 +182,7 @@ Job.NoRecentBuildFailed=No recent builds failed.
Job.Pronoun=Project
Job.minutes=mins
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
Label.ProvisionedFrom=Provisioned from {0}
......
......@@ -20,8 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
NewJob=Nouvelle {0}
People=Utilsateurs
NewJob=Nouveau {0}
People=Utilisateurs
Build\ History=Historique des constructions
Edit\ View=\u00C9diter cette vue
Delete\ View=Supprimer cette vue
......
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Free\ Space\ Threshold=Limite de espa\u00e7o livre
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
# Disk space is too low. Only {0}GB left on {1}.
blurb=Espa\u00e7o em disco est\u00e1 acabando, apenas {0}Gb livre em {1}.
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
ClockMonitor.DisplayName=Diferen\u00e7a de tempo
ResponseTimeMonitor.TimeOut=Time out da tentativa {0}
AbstractNodeMonitorDescriptor.NoDataYet=Sem informa\u00e7\u00e3o
TemporarySpaceMonitor.DisplayName=Espa\u00e7o de \u00e1rea tempor\u00e1ria
DiskSpaceMonitor.MarkedOnline=Colocar {0} online novamente se existir espa\u00e7o em disco suficiente
ResponseTimeMonitor.DisplayName=Tempo de resposta
DiskSpaceMonitor.MarkedOffline=Deixar {0} temporariamente offline devido \u00e0 falta de espa\u00e7o em disco
DiskSpaceMonitor.DisplayName=Espa\u00e7o em disco livre
SwapSpaceMonitor.DisplayName=Espa\u00e7o de swap livre
ArchitectureMonitor.DisplayName=Arquitetura
ResponseTimeMonitor.MarkedOffline=Deixar {0} offline porque n\u00e3o est\u00e1 respondendo
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Dismiss=Dispensar
blurb=O Jenkins deixou alguns slaves offlineporque a href="{0}/computer/">suas m\u00e9tricas </a> estavam abaixo do limite. \
Se voc\u00ea n\u00e3o quiser que o Jenkins fa\u00e7a isso, \
<a href="{0}/computer/configure">mude a configura\u00e7\u00e3o</a>.
# The MIT License
#
# Copyright (c) 2004-, Kohsuke Kawaguchi, Sun Microsystems, Inc., and a number of other of contributers
#
# 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.
Ping\ response\ time\ is\ too\ long\ or\ timed\ out.=O tempo de resposta do ping est\u00e1 muito alto ou deu time out
package hudson.os.windows.ManagedWindowsServiceAccount.AnotherUser;
def f = namespace(lib.FormTagLib)
f.entry (title:_("User name"),field:"userName") {
f.textbox()
}
f.entry (title:_("Password"),field:"password") {
f.password()
}
\ No newline at end of file
package hudson.os.windows.ManagedWindowsServiceAccount;
\ No newline at end of file
<!--
The MIT License
Copyright (c) 2010, InfraDNA, 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:f="/lib/form">
<f:entry title="${%Administrator user name}" field="userName">
<f:textbox />
</f:entry>
<f:entry title="${%Password}" field="password">
<f:password />
</f:entry>
</j:jelly>
\ No newline at end of file
package hudson.os.windows.ManagedWindowsServiceLauncher.AccountInfo;
def f=namespace(lib.FormTagLib)
f.entry (title:_("User name"),field:"userName") {
f.textbox()
}
f.entry (title:_("Password"),field:"password") {
f.password()
}
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, 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:f="/lib/form">
<f:entry>${%blurb}</f:entry>
<f:entry title="${%Administrator user name}" field="userName">
<f:textbox />
</f:entry>
<f:entry title="${%Password}" field="password">
<f:password />
</f:entry>
<f:entry title="${%Host}" field="host">
<f:textbox/>
</f:entry>
<f:dropdownDescriptorSelector field="account" title="${%Run service as}"/>
<f:advanced>
<f:entry title="${%Path to java executable}" field="javaPath">
<f:textbox />
</f:entry>
<f:entry title="${%JVM options}" field="vmargs">
<f:textbox />
</f:entry>
</f:advanced>
</j:jelly>
\ No newline at end of file
blurb=\
This launch method relies on DCOM and is often associated with <a href="https://wiki.jenkins-ci.org/display/JENKINS/Windows+slaves+fail+to+start+via+DCOM" target="_blank">subtle problems</a>. \
Consider using <b>Launch slave agents using Java Web Start</b> instead, which also permits installation as a Windows service but is generally considered more reliable.
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册