提交 3dea432c 编写于 作者: J Jesse Glick

Merge branch 'master' into BuildStep-Job

......@@ -145,11 +145,24 @@ public class AnnotatedLargeText<T> extends LargeText {
return super.writeLogTo(start,w);
}
/**
* Strips annotations using a {@link PlainTextConsoleOutputStream}.
* @inheritDoc
*/
@Override
public long writeLogTo(long start, OutputStream out) throws IOException {
return super.writeLogTo(start, new PlainTextConsoleOutputStream(out));
}
/**
* Calls {@link LargeText#writeLogTo(long, OutputStream)} without stripping annotations as {@link #writeLogTo(long, OutputStream)} would.
* @inheritDoc
* @since 1.577
*/
public long writeRawLogTo(long start, OutputStream out) throws IOException {
return super.writeLogTo(start, out);
}
public long writeHtmlTo(long start, Writer w) throws IOException {
ConsoleAnnotationOutputStream caw = new ConsoleAnnotationOutputStream(
w, createAnnotator(Stapler.getCurrentRequest()), context, charset);
......
......@@ -45,7 +45,6 @@ import hudson.model.Cause.LegacyCodeCause;
import hudson.model.Descriptor.FormException;
import hudson.model.Fingerprint.RangeSet;
import hudson.model.Node.Mode;
import hudson.model.PermalinkProjectAction.Permalink;
import hudson.model.Queue.Executable;
import hudson.model.Queue.Task;
import hudson.model.labels.LabelAtom;
......@@ -109,7 +108,6 @@ import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import jenkins.model.Jenkins;
import jenkins.model.JenkinsLocationConfiguration;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.ParameterizedJobMixIn;
import jenkins.model.Uptime;
import jenkins.model.lazy.LazyBuildMixIn;
......@@ -143,7 +141,7 @@ import org.kohsuke.stapler.interceptor.RequirePOST;
* @see AbstractBuild
*/
@SuppressWarnings("rawtypes")
public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends Job<P,R> implements BuildableItem, ModelObjectWithChildren, LazyBuildMixIn.LazyLoadingJob<P,R>, ParameterizedJobMixIn.ParameterizedJob {
public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends Job<P,R> implements BuildableItem, LazyBuildMixIn.LazyLoadingJob<P,R>, ParameterizedJobMixIn.ParameterizedJob {
/**
* {@link SCM} associated with the project.
......@@ -1191,11 +1189,11 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
}
public void checkAbortPermission() {
checkPermission(AbstractProject.ABORT);
checkPermission(CANCEL);
}
public boolean hasAbortPermission() {
return hasPermission(AbstractProject.ABORT);
return hasPermission(CANCEL);
}
/**
......@@ -1865,17 +1863,6 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
return r;
}
public ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse response) throws Exception {
// not sure what would be really useful here. This needs more thoughts.
// for the time being, I'm starting with permalinks
ContextMenu menu = new ContextMenu();
for (Permalink p : getPermalinks()) {
if (p.resolve(this)!=null)
menu.add(p.getId(),p.getDisplayName());
}
return menu;
}
/**
* Serves the workspace files.
*/
......@@ -2175,7 +2162,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
private static final Logger LOGGER = Logger.getLogger(AbstractProject.class.getName());
/**
* Permission to abort a build
* @deprecated Just use {@link #CANCEL}.
*/
public static final Permission ABORT = CANCEL;
......
......@@ -226,6 +226,7 @@ public interface Item extends PersistenceRoot, SearchableModelObject, AccessCont
Permission READ = new Permission(PERMISSIONS, "Read", Messages._Item_READ_description(), Permission.READ, PermissionScope.ITEM);
Permission DISCOVER = new Permission(PERMISSIONS, "Discover", Messages._AbstractProject_DiscoverPermission_Description(), Permission.READ, PermissionScope.ITEM);
Permission EXTENDED_READ = new Permission(PERMISSIONS,"ExtendedRead", Messages._AbstractProject_ExtendedReadPermission_Description(), CONFIGURE, Boolean.getBoolean("hudson.security.ExtendedReadPermission"), new PermissionScope[]{PermissionScope.ITEM});
// TODO the following really belong in Job, not Item, but too late to move since the owner.name is encoded in the ID:
Permission BUILD = new Permission(PERMISSIONS, "Build", Messages._AbstractProject_BuildPermission_Description(), Permission.UPDATE, PermissionScope.ITEM);
Permission WORKSPACE = new Permission(PERMISSIONS, "Workspace", Messages._AbstractProject_WorkspacePermission_Description(), Permission.READ, PermissionScope.ITEM);
Permission WIPEOUT = new Permission(PERMISSIONS, "WipeOut", Messages._AbstractProject_WipeOutPermission_Description(), null, Functions.isWipeOutPermissionEnabled(), new PermissionScope[]{PermissionScope.ITEM});
......
......@@ -100,6 +100,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import static javax.servlet.http.HttpServletResponse.*;
import jenkins.model.ModelObjectWithChildren;
import jenkins.model.lazy.LazyBuildMixIn;
/**
......@@ -114,7 +115,7 @@ import jenkins.model.lazy.LazyBuildMixIn;
* @author Kohsuke Kawaguchi
*/
public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, RunT>>
extends AbstractItem implements ExtensionPoint, StaplerOverridable, OnMaster {
extends AbstractItem implements ExtensionPoint, StaplerOverridable, ModelObjectWithChildren, OnMaster {
/**
* Next build number. Kept in a separate file because this is the only
......@@ -998,6 +999,18 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
return permalinks;
}
@Override public ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse response) throws Exception {
// not sure what would be really useful here. This needs more thoughts.
// for the time being, I'm starting with permalinks
ContextMenu menu = new ContextMenu();
for (Permalink p : getPermalinks()) {
if (p.resolve(this) != null) {
menu.add(p.getId(), p.getDisplayName());
}
}
return menu;
}
/**
* Used as the color of the status ball for the project.
*/
......
......@@ -1205,6 +1205,7 @@ public class Queue extends ResourceController implements Saveable {
/**
* Works just like {@link #checkAbortPermission()} except it indicates the status by a return value,
* instead of exception.
* Also used by default for {@link hudson.model.Queue.Item#hasCancelPermission}.
*/
boolean hasAbortPermission();
......@@ -1479,6 +1480,10 @@ public class Queue extends ResourceController implements Saveable {
return s.toString();
}
/**
* Checks whether a scheduled item may be canceled.
* @return by default, the same as {@link hudson.model.Queue.Task#hasAbortPermission}
*/
public boolean hasCancelPermission() {
return task.hasAbortPermission();
}
......
......@@ -459,6 +459,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
* Gets all the users.
*/
public static Collection<User> getAll() {
final IdStrategy strategy = idStrategy();
if(System.currentTimeMillis() -lastScanned>10000) {
// occasionally scan the file system to check new users
// whether we should do this only once at start up or not is debatable.
......@@ -471,7 +472,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
for (File subdir : subdirs)
if(new File(subdir,"config.xml").exists()) {
String name = subdir.getName();
String name = strategy.idFromFilename(subdir.getName());
User.getOrCreate(name, name, true);
}
......@@ -486,7 +487,6 @@ public class User extends AbstractModelObject implements AccessControlled, Descr
byNameLock.readLock().unlock();
}
Collections.sort(r,new Comparator<User>() {
IdStrategy strategy = idStrategy();
public int compare(User o1, User o2) {
return strategy.compare(o1.getId(), o2.getId());
......
......@@ -57,6 +57,16 @@ public abstract class IdStrategy extends AbstractDescribableImpl<IdStrategy> imp
@Nonnull
public abstract String filenameOf(@Nonnull String id);
/**
* Converts a filename into the corresponding id.
* @param filename the filename.
* @return the corresponding id.
* @since 1.577
*/
public String idFromFilename(@Nonnull String filename) {
return filename;
}
/**
* Converts an ID into a key for use in a Java Map.
*
......@@ -214,6 +224,59 @@ public abstract class IdStrategy extends AbstractDescribableImpl<IdStrategy> imp
}
}
@Override
public String idFromFilename(@Nonnull String filename) {
if (filename.matches("[a-z0-9_. -]+")) {
return filename;
} else {
StringBuilder buf = new StringBuilder(filename.length());
final char[] chars = filename.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if ('a' <= c && c <= 'z') {
buf.append(c);
} else if ('0' <= c && c <= '9') {
buf.append(c);
} else if ('_' == c || '.' == c || '-' == c || ' ' == c || '@' == c) {
buf.append(c);
} else if (c == '~') {
i++;
if (i < chars.length) {
buf.append(Character.toUpperCase(chars[i]));
}
} else if (c == '$') {
StringBuilder hex = new StringBuilder(4);
i++;
if (i < chars.length) {
hex.append(chars[i]);
} else {
break;
}
i++;
if (i < chars.length) {
hex.append(chars[i]);
} else {
break;
}
i++;
if (i < chars.length) {
hex.append(chars[i]);
} else {
break;
}
i++;
if (i < chars.length) {
hex.append(chars[i]);
} else {
break;
}
buf.append(Character.valueOf((char)Integer.parseInt(hex.toString(), 16)));
}
}
return buf.toString();
}
}
/**
* {@inheritDoc}
*/
......
......@@ -25,7 +25,6 @@
package jenkins.model;
import hudson.Util;
import static hudson.model.AbstractProject.ABORT;
import hudson.model.Action;
import hudson.model.BuildableItem;
import hudson.model.Cause;
......@@ -206,7 +205,7 @@ public abstract class ParameterizedJobMixIn<JobT extends Job<JobT, RunT> & Param
*/
@RequirePOST
public final void doCancelQueue( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
asJob().checkPermission(ABORT);
asJob().checkPermission(Item.CANCEL);
Jenkins.getInstance().getQueue().cancel(asJob());
rsp.forwardToPreviousPage(req);
}
......
......@@ -70,7 +70,7 @@ AbstractProject.DiscoverPermission.Description=\
AbstractProject.WipeOutPermission.Description=\
This permission grants the ability to wipe out the contents of a workspace.
AbstractProject.CancelPermission.Description=\
This permission grants the ability to cancel a build.
This permission grants the ability to cancel a scheduled, or abort a running, build.
AbstractProject.AssignedLabelString.InvalidBooleanExpression=\
Invalid boolean expression: {0}
AbstractProject.AssignedLabelString.NoMatch=\
......@@ -314,11 +314,11 @@ ChoiceParameterDefinition.MissingChoices=Requires Choices.
RunParameterDefinition.DisplayName=Run Parameter
PasswordParameterDefinition.DisplayName=Password Parameter
Node.BecauseNodeIsReserved={0} is reserved for jobs tied to it
Node.BecauseNodeIsReserved={0} is reserved for jobs with matching label expression
Node.LabelMissing={0} doesn\u2019t have label {1}
Node.LackingBuildPermission={0} doesn\u2019t have a permission to run on {1}
Node.Mode.NORMAL=Utilize this node as much as possible
Node.Mode.EXCLUSIVE=Leave this node for tied jobs only
Node.Mode.EXCLUSIVE=Only build jobs with label restrictions matching this node
ListView.DisplayName=List View
......
# This file is under the MIT License by authors
updates\ available=dotupn\u00E9 aktualizace
updates\ available=dostupn\u00E9 aktualizace
......@@ -174,6 +174,8 @@ public class UserTest {
User user = User.get("john smith");
User user2 = User.get("John Smith");
assertSame("Users should have the same id.", user.getId(), user2.getId());
assertEquals(user.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user.getId())));
assertEquals(user2.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user2.getId())));
}
@Test
......@@ -191,6 +193,8 @@ public class UserTest {
assertEquals("john smith", User.idStrategy().filenameOf(user.getId()));
assertEquals("John Smith", User.idStrategy().keyFor(user2.getId()));
assertEquals("~john ~smith", User.idStrategy().filenameOf(user2.getId()));
assertEquals(user.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user.getId())));
assertEquals(user2.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user2.getId())));
}
@Test
......@@ -212,6 +216,8 @@ public class UserTest {
assertEquals("Users should have the same id.", user.getId(), user2.getId());
assertEquals("john.smith@acme.org", User.idStrategy().keyFor(user2.getId()));
assertEquals("john.smith@acme.org", User.idStrategy().filenameOf(user2.getId()));
assertEquals(user.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user.getId())));
assertEquals(user2.getId(), User.idStrategy().idFromFilename(User.idStrategy().filenameOf(user2.getId())));
}
@Test
......
......@@ -12,11 +12,12 @@
</dd>
<dt><b>
Leave this node for tied jobs only
Only build jobs with label restrictions matching this node
</b></dt>
<dd>
In this mode, Jenkins will only build a project on this node when
that project specifically was tied to that node.
that project is restricted to certain nodes using a label expression,
and that expression matches this node&apos;s name and/or labels.
This allows a slave to be reserved for certain kinds of jobs.
For example, to run performance tests continuously from Jenkins,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册