diff options
19 files changed, 233 insertions, 219 deletions
@@ -11,8 +11,8 @@ <classpathentry kind="lib" path="ext/javawriter-2.1.1.jar" sourcepath="ext/src/javawriter-2.1.1.jar" /> <classpathentry kind="lib" path="ext/annotations-12.0.jar" sourcepath="ext/src/annotations-12.0.jar" /> <classpathentry kind="lib" path="ext/log4j-1.2.17.jar" sourcepath="ext/src/log4j-1.2.17.jar" /> - <classpathentry kind="lib" path="ext/slf4j-api-1.6.6.jar" sourcepath="ext/src/slf4j-api-1.6.6.jar" /> - <classpathentry kind="lib" path="ext/slf4j-log4j12-1.6.6.jar" sourcepath="ext/src/slf4j-log4j12-1.6.6.jar" /> + <classpathentry kind="lib" path="ext/slf4j-api-1.7.5.jar" /> + <classpathentry kind="lib" path="ext/slf4j-log4j12-1.7.5.jar" /> <classpathentry kind="lib" path="ext/mail-1.4.3.jar" sourcepath="ext/src/mail-1.4.3.jar" /> <classpathentry kind="lib" path="ext/javax.servlet-api-3.1.0.jar" sourcepath="ext/src/javax.servlet-api-3.1.0.jar" /> <classpathentry kind="lib" path="ext/jetty-all-9.1.4.v20140401.jar" sourcepath="ext/src/jetty-all-9.1.4.v20140401.jar" /> @@ -75,7 +75,7 @@ <classpathentry kind="lib" path="ext/args4j-2.0.26.jar" sourcepath="ext/src/args4j-2.0.26.jar" /> <classpathentry kind="lib" path="ext/jedis-2.3.1.jar" sourcepath="ext/src/jedis-2.3.1.jar" /> <classpathentry kind="lib" path="ext/commons-pool2-2.0.jar" sourcepath="ext/src/commons-pool2-2.0.jar" /> - <classpathentry kind="lib" path="ext/pf4j-0.7.1.jar" sourcepath="ext/src/pf4j-0.7.1.jar" /> + <classpathentry kind="lib" path="ext/pf4j-0.8.0.jar" sourcepath="ext/src/pf4j-0.8.0.jar" /> <classpathentry kind="lib" path="ext/junit-4.11.jar" sourcepath="ext/src/junit-4.11.jar" /> <classpathentry kind="lib" path="ext/hamcrest-core-1.3.jar" sourcepath="ext/src/hamcrest-core-1.3.jar" /> <classpathentry kind="lib" path="ext/selenium-java-2.28.0.jar" sourcepath="ext/src/selenium-java-2.28.0.jar" /> diff --git a/build.moxie b/build.moxie index 0f7ac81f..7b5aa210 100644 --- a/build.moxie +++ b/build.moxie @@ -131,8 +131,8 @@ dependencies: # Standard dependencies - compile 'com.intellij:annotations:12.0' :war - compile 'log4j:log4j:1.2.17' :war :fedclient :authority -- compile 'org.slf4j:slf4j-api:1.6.6' :war :fedclient :authority -- compile 'org.slf4j:slf4j-log4j12:1.6.6' :war :fedclient :authority +- compile 'org.slf4j:slf4j-api:1.7.5' :war :fedclient :authority +- compile 'org.slf4j:slf4j-log4j12:1.7.5' :war :fedclient :authority - compile 'javax.mail:mail:1.4.3' :war :authority - compile 'javax.servlet:javax.servlet-api:3.1.0' :fedclient - compile 'org.eclipse.jetty.aggregate:jetty-all:${jetty.version}' @jar @@ -173,7 +173,7 @@ dependencies: - compile 'args4j:args4j:2.0.26' :war :fedclient :authority - compile 'commons-codec:commons-codec:1.7' :war - compile 'redis.clients:jedis:2.3.1' :war -- compile 'ro.fortsoft.pf4j:pf4j:0.7.1' :war +- compile 'ro.fortsoft.pf4j:pf4j:0.8.0' :war - test 'junit' # Dependencies for Selenium web page testing - test 'org.seleniumhq.selenium:selenium-java:${selenium.version}' @jar diff --git a/gitblit.iml b/gitblit.iml index 69bd8e46..48a1c226 100644 --- a/gitblit.iml +++ b/gitblit.iml @@ -80,25 +80,21 @@ </library> </orderEntry> <orderEntry type="module-library"> - <library name="slf4j-api-1.6.6.jar"> + <library name="slf4j-api-1.7.5.jar"> <CLASSES> - <root url="jar://$MODULE_DIR$/ext/slf4j-api-1.6.6.jar!/" /> + <root url="jar://$MODULE_DIR$/ext/slf4j-api-1.7.5.jar!/" /> </CLASSES> <JAVADOC /> - <SOURCES> - <root url="jar://$MODULE_DIR$/ext/src/slf4j-api-1.6.6.jar!/" /> - </SOURCES> + <SOURCES /> </library> </orderEntry> <orderEntry type="module-library"> - <library name="slf4j-log4j12-1.6.6.jar"> + <library name="slf4j-log4j12-1.7.5.jar"> <CLASSES> - <root url="jar://$MODULE_DIR$/ext/slf4j-log4j12-1.6.6.jar!/" /> + <root url="jar://$MODULE_DIR$/ext/slf4j-log4j12-1.7.5.jar!/" /> </CLASSES> <JAVADOC /> - <SOURCES> - <root url="jar://$MODULE_DIR$/ext/src/slf4j-log4j12-1.6.6.jar!/" /> - </SOURCES> + <SOURCES /> </library> </orderEntry> <orderEntry type="module-library"> @@ -780,13 +776,13 @@ </library> </orderEntry> <orderEntry type="module-library"> - <library name="pf4j-0.7.1.jar"> + <library name="pf4j-0.8.0.jar"> <CLASSES> - <root url="jar://$MODULE_DIR$/ext/pf4j-0.7.1.jar!/" /> + <root url="jar://$MODULE_DIR$/ext/pf4j-0.8.0.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES> - <root url="jar://$MODULE_DIR$/ext/src/pf4j-0.7.1.jar!/" /> + <root url="jar://$MODULE_DIR$/ext/src/pf4j-0.8.0.jar!/" /> </SOURCES> </library> </orderEntry> diff --git a/releases.moxie b/releases.moxie index f683f2bd..15d333d4 100644 --- a/releases.moxie +++ b/releases.moxie @@ -21,8 +21,10 @@ r22: { - Repository mailing lists could not be reset from the Edit Repository page (issue-399) - Fix intermittent NPE in determining commit date in RefModel (issue-401) - Fix closing ticket on push by parsing commit messages for closes|fixes (issue-404) + - Fix diffstat display for a ticket with a pending submodule change (issue-407) - Ensure the Lucene ticket index is updated on repository deletion. - Fixed failure to properly determine hasTicket in RedisTicketService + - Fixed handling of pushing ticket branch deletions changes: - Switch from GoogleCharts to self-hosted flotr2 charts (issue-283, ticket-43, pr-166) - Specify the --dailyLogFile option for the Ubuntu and CentOS service scripts (issue-348) @@ -47,7 +49,8 @@ r22: { - args4j 2.0.26 - JGit 3.3.1 - Mina SSHD 0.10.1 - - pf4j 0.7.1 + - pf4j 0.8.0 + - SLF4J 1.7.5 contributors: - James Moger - David Ostrovsky @@ -55,6 +58,8 @@ r22: { - Jeremie Brebec - Tim Ryan - Decebal Suiu + - Eric Myrhe + - Kevin Walter settings: - { name: 'realm.ldap.bindpattern', defaultValue: ' ' } - { name: 'tickets.closeOnPushCommitMessageRegex', defaultValue: '(?:fixes|closes)[\\s-]+#?(\\d+)' } diff --git a/src/main/java/com/gitblit/DaggerModule.java b/src/main/java/com/gitblit/DaggerModule.java index e448867a..b89f8c44 100644 --- a/src/main/java/com/gitblit/DaggerModule.java +++ b/src/main/java/com/gitblit/DaggerModule.java @@ -185,6 +185,7 @@ public class DaggerModule { @Provides @Singleton GitBlitWebApp provideWebApplication( IRuntimeManager runtimeManager, + IPluginManager pluginManager, INotificationManager notificationManager, IUserManager userManager, IAuthenticationManager authenticationManager, @@ -196,6 +197,7 @@ public class DaggerModule { return new GitBlitWebApp( runtimeManager, + pluginManager, notificationManager, userManager, authenticationManager, diff --git a/src/test/java/com/gitblit/tests/ActivityTest.java b/src/main/java/com/gitblit/extensions/GitblitPlugin.java index b7382b87..129f584c 100644 --- a/src/test/java/com/gitblit/tests/ActivityTest.java +++ b/src/main/java/com/gitblit/extensions/GitblitPlugin.java @@ -1,32 +1,27 @@ -/*
- * Copyright 2011 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.tests;
-
-import java.io.IOException;
-
-import org.junit.Test;
-
-import com.gitblit.models.GravatarProfile;
-import com.gitblit.utils.ActivityUtils;
-
-public class ActivityTest extends GitblitUnitTest {
-
- @Test
- public void testGravatarProfile() throws IOException {
- GravatarProfile profile = ActivityUtils.getGravatarProfile("beau@dentedreality.com.au");
- assertEquals("beau", profile.preferredUsername);
- }
-}
\ No newline at end of file +/* + * Copyright 2014 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.extensions; + +import ro.fortsoft.pf4j.Plugin; +import ro.fortsoft.pf4j.PluginWrapper; + +public abstract class GitblitPlugin extends Plugin { + + public GitblitPlugin(PluginWrapper wrapper) { + super(wrapper); + } + +} diff --git a/src/main/java/com/gitblit/git/PatchsetReceivePack.java b/src/main/java/com/gitblit/git/PatchsetReceivePack.java index 77d5a71e..43efc54a 100644 --- a/src/main/java/com/gitblit/git/PatchsetReceivePack.java +++ b/src/main/java/com/gitblit/git/PatchsetReceivePack.java @@ -309,6 +309,7 @@ public class PatchsetReceivePack extends GitblitReceivePack { }
if (isPatchsetRef(cmd.getRefName()) && processPatchsets) {
+
if (ticketService == null) {
sendRejection(cmd, "Sorry, the ticket service is unavailable and can not accept patchsets at this time.");
continue;
@@ -346,6 +347,20 @@ public class PatchsetReceivePack extends GitblitReceivePack { continue;
}
+ if (cmd.getNewId().equals(ObjectId.zeroId())) {
+ // ref deletion request
+ if (cmd.getRefName().startsWith(Constants.R_TICKET)) {
+ if (user.canDeleteRef(repository)) {
+ batch.addCommand(cmd);
+ } else {
+ sendRejection(cmd, "Sorry, you do not have permission to delete {}", cmd.getRefName());
+ }
+ } else {
+ sendRejection(cmd, "Sorry, you can not delete {}", cmd.getRefName());
+ }
+ continue;
+ }
+
if (patchsetRefCmd != null) {
sendRejection(cmd, "You may only push one patchset at a time.");
continue;
diff --git a/src/main/java/com/gitblit/manager/GitblitManager.java b/src/main/java/com/gitblit/manager/GitblitManager.java index 56a71d41..4ecb9c6d 100644 --- a/src/main/java/com/gitblit/manager/GitblitManager.java +++ b/src/main/java/com/gitblit/manager/GitblitManager.java @@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory; import ro.fortsoft.pf4j.PluginState; import ro.fortsoft.pf4j.PluginWrapper; +import ro.fortsoft.pf4j.Version; import com.gitblit.Constants; import com.gitblit.Constants.AccessPermission; @@ -1190,6 +1191,11 @@ public class GitblitManager implements IGitblit { */ @Override + public Version getSystemVersion() { + return pluginManager.getSystemVersion(); + } + + @Override public void startPlugins() { pluginManager.startPlugins(); } diff --git a/src/main/java/com/gitblit/manager/IPluginManager.java b/src/main/java/com/gitblit/manager/IPluginManager.java index 317cff73..bf04619c 100644 --- a/src/main/java/com/gitblit/manager/IPluginManager.java +++ b/src/main/java/com/gitblit/manager/IPluginManager.java @@ -20,6 +20,7 @@ import java.util.List; import ro.fortsoft.pf4j.PluginState; import ro.fortsoft.pf4j.PluginWrapper; +import ro.fortsoft.pf4j.Version; import com.gitblit.models.PluginRegistry.InstallState; import com.gitblit.models.PluginRegistry.PluginRegistration; @@ -28,6 +29,13 @@ import com.gitblit.models.PluginRegistry.PluginRelease; public interface IPluginManager extends IManager { /** + * Returns the system version. + * + * @return the system version + */ + Version getSystemVersion(); + + /** * Starts all plugins. */ void startPlugins(); diff --git a/src/main/java/com/gitblit/manager/PluginManager.java b/src/main/java/com/gitblit/manager/PluginManager.java index b2a87ab3..405dc510 100644 --- a/src/main/java/com/gitblit/manager/PluginManager.java +++ b/src/main/java/com/gitblit/manager/PluginManager.java @@ -42,9 +42,10 @@ import ro.fortsoft.pf4j.PluginClassLoader; import ro.fortsoft.pf4j.PluginState; import ro.fortsoft.pf4j.PluginStateEvent; import ro.fortsoft.pf4j.PluginStateListener; -import ro.fortsoft.pf4j.PluginVersion; import ro.fortsoft.pf4j.PluginWrapper; +import ro.fortsoft.pf4j.Version; +import com.gitblit.Constants; import com.gitblit.Keys; import com.gitblit.models.PluginRegistry; import com.gitblit.models.PluginRegistry.InstallState; @@ -63,6 +64,7 @@ import com.google.common.io.InputSupplier; * the Dagger DI and retrieve extensions provided by active plugins. * * @author David Ostrovsky + * @author James Moger * */ public class PluginManager implements IPluginManager, PluginStateListener { @@ -82,7 +84,20 @@ public class PluginManager implements IPluginManager, PluginStateListener { File dir = runtimeManager.getFileOrFolder(Keys.plugins.folder, "${baseFolder}/plugins"); dir.mkdirs(); this.runtimeManager = runtimeManager; + this.pf4j = new DefaultPluginManager(dir); + + try { + Version systemVersion = Version.createVersion(Constants.getVersion()); + pf4j.setSystemVersion(systemVersion); + } catch (Exception e) { + logger.error(null, e); + } + } + + @Override + public Version getSystemVersion() { + return pf4j.getSystemVersion(); } @Override @@ -130,6 +145,7 @@ public class PluginManager implements IPluginManager, PluginStateListener { return PluginState.STARTED.equals(state); } + @Override public synchronized boolean upgradePlugin(String pluginId, String url, boolean verifyChecksum) throws IOException { // ensure we can download the update BEFORE we remove the existing one File file = download(url, verifyChecksum); @@ -185,7 +201,6 @@ public class PluginManager implements IPluginManager, PluginStateListener { (file.getName().toLowerCase().endsWith(".sha1") || file.getName().toLowerCase().endsWith(".md5")); } - }); if (checksums != null) { @@ -322,7 +337,7 @@ public class PluginManager implements IPluginManager, PluginStateListener { for (PluginWrapper pw : pf4j.getPlugins()) { String id = pw.getDescriptor().getPluginId(); - PluginVersion pv = pw.getDescriptor().getVersion(); + Version pv = pw.getDescriptor().getVersion(); PluginRegistration reg = map.get(id); if (reg != null) { reg.installedRelease = pv.toString(); diff --git a/src/main/java/com/gitblit/models/GravatarProfile.java b/src/main/java/com/gitblit/models/GravatarProfile.java deleted file mode 100644 index ec1aeea3..00000000 --- a/src/main/java/com/gitblit/models/GravatarProfile.java +++ /dev/null @@ -1,83 +0,0 @@ -/*
- * Copyright 2011 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.models;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * Represents a Gravatar profile.
- *
- * @author James Moger
- *
- */
-public class GravatarProfile implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- public String id;
- public String hash;
- public String requestHash;
- public String displayName;
- public String preferredUsername;
- public String currentLocation;
- public String aboutMe;
-
- public String profileUrl;
- public String thumbnailUrl;
- public List<ProfileObject> photos;
-// public Map<String, String> profileBackground;
-// public Map<String, String> name;
-
- public List<ProfileObject> phoneNumbers;
- public List<ProfileObject> emails;
- public List<ProfileObject> ims;
- public List<Account> accounts;
- public List<ProfileObject> urls;
-
- public static class ProfileObject implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- public String title;
- public String type;
- public String value;
- public boolean primary;
-
- @Override
- public String toString() {
- return value;
- }
- }
-
- public static class Account implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- public String domain;
- public String display;
- public String url;
- public String username;
- public String userid;
- public boolean verified;
- public String shortname;
-
- @Override
- public String toString() {
- return display;
- }
- }
-}
diff --git a/src/main/java/com/gitblit/models/PluginRegistry.java b/src/main/java/com/gitblit/models/PluginRegistry.java index 7c1927f5..ef463163 100644 --- a/src/main/java/com/gitblit/models/PluginRegistry.java +++ b/src/main/java/com/gitblit/models/PluginRegistry.java @@ -23,7 +23,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import org.parboiled.common.StringUtils;
-import ro.fortsoft.pf4j.PluginVersion;
+import ro.fortsoft.pf4j.Version;
/**
* Represents a list of plugin registrations.
@@ -125,8 +125,8 @@ public class PluginRegistry implements Serializable { if (StringUtils.isEmpty(installedRelease)) {
return InstallState.NOT_INSTALLED;
}
- PluginVersion ir = PluginVersion.createVersion(installedRelease);
- PluginVersion cr = PluginVersion.createVersion(currentRelease);
+ Version ir = Version.createVersion(installedRelease);
+ Version cr = Version.createVersion(currentRelease);
switch (ir.compareTo(cr)) {
case -1:
return InstallState.UNKNOWN;
@@ -151,7 +151,7 @@ public class PluginRegistry implements Serializable { @Override
public int compareTo(PluginRelease o) {
- return PluginVersion.createVersion(version).compareTo(PluginVersion.createVersion(o.version));
+ return Version.createVersion(version).compareTo(Version.createVersion(o.version));
}
}
}
diff --git a/src/main/java/com/gitblit/servlet/GitblitContext.java b/src/main/java/com/gitblit/servlet/GitblitContext.java index 553651da..b865750b 100644 --- a/src/main/java/com/gitblit/servlet/GitblitContext.java +++ b/src/main/java/com/gitblit/servlet/GitblitContext.java @@ -177,7 +177,6 @@ public class GitblitContext extends DaggerContext { managers.add(runtime); // start all other managers - startManager(injector, IPluginManager.class); startManager(injector, INotificationManager.class); startManager(injector, IUserManager.class); startManager(injector, IAuthenticationManager.class); @@ -187,6 +186,10 @@ public class GitblitContext extends DaggerContext { startManager(injector, IFederationManager.class); startManager(injector, IGitblit.class); + // start the plugin manager last so that plugins can depend on + // deterministic access to all other managers in their start() methods + startManager(injector, IPluginManager.class); + logger.info(""); logger.info("All managers started."); logger.info(""); diff --git a/src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java b/src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java index f5b68548..37649ead 100644 --- a/src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java +++ b/src/main/java/com/gitblit/transport/ssh/commands/PluginDispatcher.java @@ -27,6 +27,7 @@ import ro.fortsoft.pf4j.PluginDependency; import ro.fortsoft.pf4j.PluginDescriptor; import ro.fortsoft.pf4j.PluginState; import ro.fortsoft.pf4j.PluginWrapper; +import ro.fortsoft.pf4j.Version; import com.gitblit.manager.IGitblit; import com.gitblit.models.PluginRegistry.InstallState; @@ -35,6 +36,7 @@ import com.gitblit.models.PluginRegistry.PluginRelease; import com.gitblit.models.UserModel; import com.gitblit.utils.FlipTable; import com.gitblit.utils.FlipTable.Borders; +import com.gitblit.utils.StringUtils; import com.google.common.base.Joiner; /** @@ -75,7 +77,7 @@ public class PluginDispatcher extends DispatchCommand { protected void asTable(List<PluginWrapper> list) { String[] headers; if (verbose) { - String [] h = { "#", "Id", "Description", "Version", "Requires", "State", "Path", "Provider"}; + String [] h = { "#", "Id", "Description", "Version", "Requires", "State", "Path" }; headers = h; } else { String [] h = { "#", "Id", "Version", "State", "Path"}; @@ -86,7 +88,7 @@ public class PluginDispatcher extends DispatchCommand { PluginWrapper p = list.get(i); PluginDescriptor d = p.getDescriptor(); if (verbose) { - data[i] = new Object[] { "" + (i + 1), d.getPluginId(), null/*d.getDescription()*/, d.getVersion(), null/*d.getRequires()*/, p.getPluginState(), p.getPluginPath(), d.getProvider() }; + data[i] = new Object[] { "" + (i + 1), d.getPluginId(), d.getPluginDescription(), d.getVersion(), d.getRequires(), p.getPluginState(), p.getPluginPath() }; } else { data[i] = new Object[] { "" + (i + 1), d.getPluginId(), d.getVersion(), p.getPluginState(), p.getPluginPath() }; } @@ -100,7 +102,7 @@ public class PluginDispatcher extends DispatchCommand { for (PluginWrapper pw : list) { PluginDescriptor d = pw.getDescriptor(); if (verbose) { - outTabbed(d.getPluginId(), null/*d.getDescription()*/, d.getVersion(), null/*d.getRequires()*/, pw.getPluginState(), pw.getPluginPath(), d.getProvider()); + outTabbed(d.getPluginId(), d.getPluginDescription(), d.getVersion(), d.getRequires(), pw.getPluginState(), pw.getPluginPath()); } else { outTabbed(d.getPluginId(), d.getVersion(), pw.getPluginState(), pw.getPluginPath()); } @@ -157,7 +159,7 @@ public class PluginDispatcher extends DispatchCommand { if (PluginState.STARTED.equals(state)) { stdout.println(String.format("Started %s", pluginWrapper.getPluginId())); } else { - throw new Failure(1, String.format("Failed to start %s", pluginWrapper.getPluginId())); + throw new UnloggedFailure(1, String.format("Failed to start %s", pluginWrapper.getPluginId())); } } } @@ -185,7 +187,7 @@ public class PluginDispatcher extends DispatchCommand { if (PluginState.STOPPED.equals(state)) { stdout.println(String.format("Stopped %s", pluginWrapper.getPluginId())); } else { - throw new Failure(1, String.format("Failed to stop %s", pluginWrapper.getPluginId())); + throw new UnloggedFailure(1, String.format("Failed to stop %s", pluginWrapper.getPluginId())); } } } @@ -208,7 +210,7 @@ public class PluginDispatcher extends DispatchCommand { if (gitblit.enablePlugin(pluginWrapper.getPluginId())) { stdout.println(String.format("Enabled %s", pluginWrapper.getPluginId())); } else { - throw new Failure(1, String.format("Failed to enable %s", pluginWrapper.getPluginId())); + throw new UnloggedFailure(1, String.format("Failed to enable %s", pluginWrapper.getPluginId())); } } } @@ -230,7 +232,7 @@ public class PluginDispatcher extends DispatchCommand { if (gitblit.disablePlugin(pluginWrapper.getPluginId())) { stdout.println(String.format("Disabled %s", pluginWrapper.getPluginId())); } else { - throw new Failure(1, String.format("Failed to disable %s", pluginWrapper.getPluginId())); + throw new UnloggedFailure(1, String.format("Failed to disable %s", pluginWrapper.getPluginId())); } } } @@ -258,9 +260,9 @@ public class PluginDispatcher extends DispatchCommand { protected String buildFieldTable(PluginWrapper pw, PluginRegistration reg) { final String id = pw == null ? reg.id : pw.getPluginId(); - final String description = reg == null ? ""/*pw.getDescriptor().getDescription()*/ : reg.description; + final String description = reg == null ? pw.getDescriptor().getPluginDescription() : reg.description; final String version = pw == null ? reg.getCurrentRelease().version : pw.getDescriptor().getVersion().toString(); - final String requires = pw == null ? reg.getCurrentRelease().requires : ""/*pw.getDescriptor().getRequires().toString()*/; + final String requires = pw == null ? reg.getCurrentRelease().requires : pw.getDescriptor().getRequires().toString(); final String provider = pw == null ? reg.provider : pw.getDescriptor().getProvider(); final String registry = reg == null ? "" : reg.registry; final String path = pw == null ? "" : pw.getPluginPath(); @@ -516,22 +518,35 @@ public class PluginDispatcher extends DispatchCommand { if (gitblit.installPlugin(urlOrId, !disableChecksum)) { stdout.println(String.format("Installed %s", urlOrId)); } else { - new Failure(1, String.format("Failed to install %s", urlOrId)); + new UnloggedFailure(1, String.format("Failed to install %s", urlOrId)); } } else { - PluginRelease pv = gitblit.lookupRelease(urlOrId, version); - if (pv == null) { - throw new Failure(1, String.format("Plugin \"%s\" is not in the registry!", urlOrId)); + PluginRelease pr = gitblit.lookupRelease(urlOrId, version); + if (pr == null) { + throw new UnloggedFailure(1, String.format("Plugin \"%s\" is not in the registry!", urlOrId)); } - if (gitblit.installPlugin(pv.url, !disableChecksum)) { + + // enforce minimum system requirement + if (!StringUtils.isEmpty(pr.requires)) { + Version requires = Version.createVersion(pr.requires); + Version system = gitblit.getSystemVersion(); + boolean isValid = system.isZero() || system.atLeast(requires); + if (!isValid) { + String msg = String.format("Plugin \"%s:%s\" requires Gitblit %s", + urlOrId, pr.version, pr.requires); + throw new UnloggedFailure(1, msg); + } + } + + if (gitblit.installPlugin(pr.url, !disableChecksum)) { stdout.println(String.format("Installed %s", urlOrId)); } else { - throw new Failure(1, String.format("Failed to install %s", urlOrId)); + throw new UnloggedFailure(1, String.format("Failed to install %s", urlOrId)); } } } catch (IOException e) { log.error("Failed to install " + urlOrId, e); - throw new Failure(1, String.format("Failed to install %s", urlOrId), e); + throw new UnloggedFailure(1, String.format("Failed to install %s", urlOrId), e); } } } @@ -556,20 +571,31 @@ public class PluginDispatcher extends DispatchCommand { throw new UnloggedFailure("Invalid plugin specified!"); } - PluginRelease pv = gitblit.lookupRelease(pluginWrapper.getPluginId(), version); - if (pv == null) { - throw new Failure(1, String.format("Plugin \"%s\" is not in the registry!", pluginWrapper.getPluginId())); + PluginRelease pr = gitblit.lookupRelease(pluginWrapper.getPluginId(), version); + if (pr == null) { + throw new UnloggedFailure(1, String.format("Plugin \"%s\" is not in the registry!", pluginWrapper.getPluginId())); + } + + // enforce minimum system requirement + if (!StringUtils.isEmpty(pr.requires)) { + Version requires = Version.createVersion(pr.requires); + Version system = gitblit.getSystemVersion(); + boolean isValid = system.isZero() || system.atLeast(requires); + if (!isValid) { + throw new Failure(1, String.format("Plugin \"%s:%s\" requires Gitblit %s", + pluginWrapper.getPluginId(), pr.version, pr.requires)); + } } try { - if (gitblit.upgradePlugin(pluginWrapper.getPluginId(), pv.url, !disableChecksum)) { + if (gitblit.upgradePlugin(pluginWrapper.getPluginId(), pr.url, !disableChecksum)) { stdout.println(String.format("Upgraded %s", pluginWrapper.getPluginId())); } else { - throw new Failure(1, String.format("Failed to upgrade %s", pluginWrapper.getPluginId())); + throw new UnloggedFailure(1, String.format("Failed to upgrade %s", pluginWrapper.getPluginId())); } } catch (IOException e) { log.error("Failed to upgrade " + pluginWrapper.getPluginId(), e); - throw new Failure(1, String.format("Failed to upgrade %s", pluginWrapper.getPluginId()), e); + throw new UnloggedFailure(1, String.format("Failed to upgrade %s", pluginWrapper.getPluginId()), e); } } } @@ -591,7 +617,7 @@ public class PluginDispatcher extends DispatchCommand { if (gitblit.deletePlugin(pluginWrapper.getPluginId())) { stdout.println(String.format("Uninstalled %s", pluginWrapper.getPluginId())); } else { - throw new Failure(1, String.format("Failed to uninstall %s", pluginWrapper.getPluginId())); + throw new UnloggedFailure(1, String.format("Failed to uninstall %s", pluginWrapper.getPluginId())); } } } diff --git a/src/main/java/com/gitblit/utils/ActivityUtils.java b/src/main/java/com/gitblit/utils/ActivityUtils.java index 3a54d33f..ba5599a1 100644 --- a/src/main/java/com/gitblit/utils/ActivityUtils.java +++ b/src/main/java/com/gitblit/utils/ActivityUtils.java @@ -15,9 +15,6 @@ */
package com.gitblit.utils;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
@@ -38,11 +35,9 @@ import com.gitblit.IStoredSettings; import com.gitblit.Keys;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.Activity;
-import com.gitblit.models.GravatarProfile;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryCommit;
import com.gitblit.models.RepositoryModel;
-import com.google.gson.reflect.TypeToken;
/**
* Utility class for building activity information from repositories.
@@ -162,19 +157,6 @@ public class ActivityUtils { }
/**
- * Returns the Gravatar profile, if available, for the specified email
- * address.
- *
- * @param emailaddress
- * @return a Gravatar Profile
- * @throws IOException
- */
- public static GravatarProfile getGravatarProfileFromAddress(String emailaddress)
- throws IOException {
- return getGravatarProfile(StringUtils.getMD5(emailaddress.toLowerCase()));
- }
-
- /**
* Creates a Gravatar thumbnail url from the specified email address.
*
* @param email
@@ -211,32 +193,4 @@ public class ActivityUtils { "https://www.gravatar.com/avatar/{0}?s={1,number,0}&d=mm", emailHash, width);
return url;
}
-
- /**
- * Returns the Gravatar profile, if available, for the specified hashcode.
- * address.
- *
- * @param hash
- * the hash of the email address
- * @return a Gravatar Profile
- * @throws IOException
- */
- public static GravatarProfile getGravatarProfile(String hash) throws IOException {
- String url = MessageFormat.format("https://www.gravatar.com/{0}.json", hash);
- // Gravatar has a complex json structure
- Type profileType = new TypeToken<Map<String, List<GravatarProfile>>>() {
- }.getType();
- Map<String, List<GravatarProfile>> profiles = null;
- try {
- profiles = JsonUtils.retrieveJson(url, profileType);
- } catch (FileNotFoundException e) {
- }
- if (profiles == null || profiles.size() == 0) {
- return null;
- }
- // due to the complex json structure we need to pull out the profile
- // from a list 2 levels deep
- GravatarProfile profile = profiles.values().iterator().next().get(0);
- return profile;
- }
}
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java index 6e8aa05f..58fc5b7a 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java @@ -34,6 +34,7 @@ import com.gitblit.manager.IAuthenticationManager; import com.gitblit.manager.IFederationManager; import com.gitblit.manager.IGitblit; import com.gitblit.manager.INotificationManager; +import com.gitblit.manager.IPluginManager; import com.gitblit.manager.IProjectManager; import com.gitblit.manager.IRepositoryManager; import com.gitblit.manager.IRuntimeManager; @@ -90,6 +91,8 @@ public class GitBlitWebApp extends WebApplication { private final IRuntimeManager runtimeManager; + private final IPluginManager pluginManager; + private final INotificationManager notificationManager; private final IUserManager userManager; @@ -108,6 +111,7 @@ public class GitBlitWebApp extends WebApplication { public GitBlitWebApp( IRuntimeManager runtimeManager, + IPluginManager pluginManager, INotificationManager notificationManager, IUserManager userManager, IAuthenticationManager authenticationManager, @@ -120,6 +124,7 @@ public class GitBlitWebApp extends WebApplication { super(); this.settings = runtimeManager.getSettings(); this.runtimeManager = runtimeManager; + this.pluginManager = pluginManager; this.notificationManager = notificationManager; this.userManager = userManager; this.authenticationManager = authenticationManager; @@ -273,6 +278,10 @@ public class GitBlitWebApp extends WebApplication { return runtimeManager; } + public IPluginManager plugins() { + return pluginManager; + } + public INotificationManager notifier() { return notificationManager; } diff --git a/src/site/plugins_extensions.mkd b/src/site/plugins_extensions.mkd index d7469ac6..6e0e52e6 100644 --- a/src/site/plugins_extensions.mkd +++ b/src/site/plugins_extensions.mkd @@ -2,20 +2,56 @@ Gitblit offers several extension points for enhancing and customizing it's runtime behavior. -Each available extension point has a sample implementation in the [gitblit-cookbook-plugin (Maven project)](https://dev.gitblit.com/summary/gitblit-cookbook-plugin.git). +Each available extension point has a sample implementation in the [gitblit-cookbook-plugin (Maven project)](https://github.com/gitblit/gitblit-cookbook-plugin). + +**NOTE:** +Gitblit does not yet offer a comprehensize dependency injection architecture. This will be addressed in a subsequent release. For now you may access all of Gitblit's core managers through a static singleton app context: + +```java +import com.gitblit.extensions.GitblitPlugin; +import com.gitblit.servlet.GitblitContext; +import com.gitblit.manager.IRuntimeManager; +import com.gitblit.manager.IUserManager; +import com.gitblit.manager.IAuthenticationManager; +import com.gitblit.manager.INotificationManager; +import com.gitblit.manager.IRepositoryManager; +import com.gitblit.manager.IProjectManager; +import com.gitblit.manager.IFederationManager; +import com.gitblit.manager.IPluginManager; +import com.gitblit.manager.IGitblit; + +public class ExamplePlugin extends GitblitPlugin { + + @Override + public void start() { + IRuntimeManager runtime = GitblitContext.getManager(IRuntimeManager.class); + IUserManager users = GitblitContext.getManager(IUserManager.class); + IAuthenticationManager auth = GitblitContext.getManager(IAuthenticationManager.class); + INotificationManager notifications = GitblitContext.getManager(INotificationManager.class); + IRepositoryManager repos = GitblitContext.getManager(IRepositoryManager.class); + IProjectManager projects = GitblitContext.getManager(IProjectManager.class); + IFederationManager federation = GitblitContext.getManager(IFederationManager.class); + IPluginManager plugins = GitblitContext.getManager(IPluginManager.class); + IGitblit gitblit = GitblitContext.getManager(IGitblit.class); + } +} +``` ### SSH Dispatch Command *SINCE 1.5.0* -You can provide your own custom SSH commands by subclassing the *DispatchCommand* class. +You can provide your own custom SSH command hierarchies by subclassing the *DispatchCommand* class. ```java import ro.fortsoft.pf4j.Extension; - +import org.kohsuke.args4j.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.gitblit.models.UserModel; import com.gitblit.transport.ssh.commands.CommandMetaData; import com.gitblit.transport.ssh.commands.DispatchCommand; +import com.gitblit.transport.ssh.commands.UsageExample; @Extension @CommandMetaData(name = "mycommands", description = "Sample SSH dispatcher") @@ -31,6 +67,25 @@ public class MyDispatcher extends DispatchCommand { register(user, SubDispatcher1.class); register(user, SubDispatcher2.class); } + + @CommandMetaData(name = "commanda", aliases = { "ca" }, description = "description of command a") + @UsageExample(syntax = "${cmd} --myflag", description = "description of commanda with --myflag") + public static class CommandA extends SshCommand { + + protected final Logger log = LoggerFactory.getLogger(getClass()); + + @Option(name = "--myflag", aliases = { "-m" }, usage = "enable myflag") + boolean myflag; + + @Override + public void run() throws Failure { + if (myflag) { + log.info("Run with --myflag"); + } else { + log.info("Run without --myflag"); + } + } + } } ``` diff --git a/src/site/plugins_overview.mkd b/src/site/plugins_overview.mkd index 5cb60d07..45a54344 100644 --- a/src/site/plugins_overview.mkd +++ b/src/site/plugins_overview.mkd @@ -23,6 +23,7 @@ A plugin defines it's metadata in the META-INF/MANIFEST.MF file: Plugin-Description: Command and control Gitblit over SSH Plugin-Class: com.gitblit.plugin.powertools.Powertools Plugin-Version: 1.2.0 + Plugin-Requires: 1.5.0 Plugin-Provider: gitblit.com In addition to extending Gitblit core, plugins can also define extension points that may be implemented by other plugins. Therefore a plugin may depend on other plugins. @@ -32,9 +33,9 @@ In addition to extending Gitblit core, plugins can also define extension points **NOTE:** The pf4j plugin framework relies on a javac apt processor to generate compile-time extension information, so be sure to enable apt processing in your build process. -#### Limitations of Dependencies & Requires +#### Limitations of Dependencies -Plugins may specify dependencies by ID, but may not specify specific versions of a dependency. The plugin registry allows you to specify a *requires* version of Gitblit, but this is not currently enforced. +Plugins may specify dependencies by ID, but may not specify specific versions of a dependency. ### Managing Plugins diff --git a/src/site/setup_transport_ssh.mkd b/src/site/setup_transport_ssh.mkd index a671e5af..7b53624b 100644 --- a/src/site/setup_transport_ssh.mkd +++ b/src/site/setup_transport_ssh.mkd @@ -80,7 +80,14 @@ You can also remove all your public keys from your account. ssh -l <username> -p 29418 <hostname> keys remove ALL
-### SSH Command Plugins
+##### keys permission
+
+You may control the access permission for each SSH key. This is more of a safety feature than a security measure.
+
+| Permission | Description |
+| ---------- | ----------------------------------------------- |
+| V | SSH key may not be used for clone/fetch or push |
+| R | SSH key may be used to clone/fetch |
+| RW | SSH key may be used to clone/fetch and push |
-Gitblit supports loading custom SSH command plugins.
|