You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PluginDispatcher.java 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. /*
  2. * Copyright 2014 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.transport.ssh.commands;
  17. import java.io.IOException;
  18. import java.util.Collections;
  19. import java.util.List;
  20. import org.kohsuke.args4j.Argument;
  21. import org.kohsuke.args4j.Option;
  22. import ro.fortsoft.pf4j.ExtensionPoint;
  23. import ro.fortsoft.pf4j.PluginDependency;
  24. import ro.fortsoft.pf4j.PluginDescriptor;
  25. import ro.fortsoft.pf4j.PluginState;
  26. import ro.fortsoft.pf4j.PluginWrapper;
  27. import ro.fortsoft.pf4j.Version;
  28. import com.gitblit.manager.IGitblit;
  29. import com.gitblit.models.PluginRegistry.InstallState;
  30. import com.gitblit.models.PluginRegistry.PluginRegistration;
  31. import com.gitblit.models.PluginRegistry.PluginRelease;
  32. import com.gitblit.utils.FlipTable;
  33. import com.gitblit.utils.FlipTable.Borders;
  34. import com.gitblit.utils.StringUtils;
  35. import com.google.common.base.Joiner;
  36. /**
  37. * The plugin dispatcher and commands for runtime plugin management.
  38. *
  39. * @author James Moger
  40. *
  41. */
  42. @CommandMetaData(name = "plugin", description = "Plugin management commands", admin = true)
  43. public class PluginDispatcher extends DispatchCommand {
  44. @Override
  45. protected void setup() {
  46. register(ListPlugins.class);
  47. register(StartPlugin.class);
  48. register(StopPlugin.class);
  49. register(EnablePlugin.class);
  50. register(DisablePlugin.class);
  51. register(ShowPlugin.class);
  52. register(RefreshPlugins.class);
  53. register(AvailablePlugins.class);
  54. register(InstallPlugin.class);
  55. register(UpgradePlugin.class);
  56. register(UninstallPlugin.class);
  57. }
  58. @CommandMetaData(name = "list", aliases = { "ls" }, description = "List plugins")
  59. public static class ListPlugins extends ListCommand<PluginWrapper> {
  60. @Override
  61. protected List<PluginWrapper> getItems() throws UnloggedFailure {
  62. IGitblit gitblit = getContext().getGitblit();
  63. List<PluginWrapper> list = gitblit.getPlugins();
  64. return list;
  65. }
  66. @Override
  67. protected void asTable(List<PluginWrapper> list) {
  68. String[] headers;
  69. if (verbose) {
  70. String [] h = { "#", "Id", "Description", "Version", "Requires", "State", "Path" };
  71. headers = h;
  72. } else {
  73. String [] h = { "#", "Id", "Version", "State", "Path"};
  74. headers = h;
  75. }
  76. Object[][] data = new Object[list.size()][];
  77. for (int i = 0; i < list.size(); i++) {
  78. PluginWrapper p = list.get(i);
  79. PluginDescriptor d = p.getDescriptor();
  80. if (verbose) {
  81. data[i] = new Object[] { "" + (i + 1), d.getPluginId(), d.getPluginDescription(), d.getVersion(), d.getRequires(), p.getPluginState(), p.getPluginPath() };
  82. } else {
  83. data[i] = new Object[] { "" + (i + 1), d.getPluginId(), d.getVersion(), p.getPluginState(), p.getPluginPath() };
  84. }
  85. }
  86. stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
  87. }
  88. @Override
  89. protected void asTabbed(List<PluginWrapper> list) {
  90. for (PluginWrapper pw : list) {
  91. PluginDescriptor d = pw.getDescriptor();
  92. if (verbose) {
  93. outTabbed(d.getPluginId(), d.getPluginDescription(), d.getVersion(), d.getRequires(), pw.getPluginState(), pw.getPluginPath());
  94. } else {
  95. outTabbed(d.getPluginId(), d.getVersion(), pw.getPluginState(), pw.getPluginPath());
  96. }
  97. }
  98. }
  99. }
  100. static abstract class PluginCommand extends SshCommand {
  101. protected PluginWrapper getPlugin(String id) throws Failure {
  102. IGitblit gitblit = getContext().getGitblit();
  103. PluginWrapper pluginWrapper = null;
  104. try {
  105. int index = Integer.parseInt(id);
  106. List<PluginWrapper> plugins = gitblit.getPlugins();
  107. if (index > plugins.size()) {
  108. throw new UnloggedFailure(1, "Invalid plugin index specified!");
  109. }
  110. pluginWrapper = plugins.get(index - 1);
  111. } catch (NumberFormatException e) {
  112. pluginWrapper = gitblit.getPlugin(id);
  113. if (pluginWrapper == null) {
  114. PluginRegistration reg = gitblit.lookupPlugin(id);
  115. if (reg == null) {
  116. throw new UnloggedFailure("Invalid plugin specified!");
  117. }
  118. pluginWrapper = gitblit.getPlugin(reg.id);
  119. }
  120. }
  121. return pluginWrapper;
  122. }
  123. }
  124. @CommandMetaData(name = "start", description = "Start a plugin")
  125. public static class StartPlugin extends PluginCommand {
  126. @Argument(index = 0, required = true, metaVar = "ALL|<ID>|<INDEX>", usage = "the plugin to start")
  127. protected String id;
  128. @Override
  129. public void run() throws Failure {
  130. IGitblit gitblit = getContext().getGitblit();
  131. if (id.equalsIgnoreCase("ALL")) {
  132. gitblit.startPlugins();
  133. stdout.println("All plugins started");
  134. } else {
  135. PluginWrapper pluginWrapper = getPlugin(id);
  136. if (pluginWrapper == null) {
  137. throw new UnloggedFailure(String.format("Plugin %s is not installed!", id));
  138. }
  139. PluginState state = gitblit.startPlugin(pluginWrapper.getPluginId());
  140. if (PluginState.STARTED.equals(state)) {
  141. stdout.println(String.format("Started %s", pluginWrapper.getPluginId()));
  142. } else {
  143. throw new UnloggedFailure(1, String.format("Failed to start %s", pluginWrapper.getPluginId()));
  144. }
  145. }
  146. }
  147. }
  148. @CommandMetaData(name = "stop", description = "Stop a plugin")
  149. public static class StopPlugin extends PluginCommand {
  150. @Argument(index = 0, required = true, metaVar = "ALL|<ID>|<INDEX>", usage = "the plugin to stop")
  151. protected String id;
  152. @Override
  153. public void run() throws Failure {
  154. IGitblit gitblit = getContext().getGitblit();
  155. if (id.equalsIgnoreCase("ALL")) {
  156. gitblit.stopPlugins();
  157. stdout.println("All plugins stopped");
  158. } else {
  159. PluginWrapper pluginWrapper = getPlugin(id);
  160. if (pluginWrapper == null) {
  161. throw new UnloggedFailure(String.format("Plugin %s is not installed!", id));
  162. }
  163. PluginState state = gitblit.stopPlugin(pluginWrapper.getPluginId());
  164. if (PluginState.STOPPED.equals(state)) {
  165. stdout.println(String.format("Stopped %s", pluginWrapper.getPluginId()));
  166. } else {
  167. throw new UnloggedFailure(1, String.format("Failed to stop %s", pluginWrapper.getPluginId()));
  168. }
  169. }
  170. }
  171. }
  172. @CommandMetaData(name = "enable", description = "Enable a plugin")
  173. public static class EnablePlugin extends PluginCommand {
  174. @Argument(index = 0, required = true, metaVar = "<ID>|<INDEX>", usage = "the plugin to enable")
  175. protected String id;
  176. @Override
  177. public void run() throws Failure {
  178. IGitblit gitblit = getContext().getGitblit();
  179. PluginWrapper pluginWrapper = getPlugin(id);
  180. if (pluginWrapper == null) {
  181. throw new UnloggedFailure("Invalid plugin specified!");
  182. }
  183. if (gitblit.enablePlugin(pluginWrapper.getPluginId())) {
  184. stdout.println(String.format("Enabled %s", pluginWrapper.getPluginId()));
  185. } else {
  186. throw new UnloggedFailure(1, String.format("Failed to enable %s", pluginWrapper.getPluginId()));
  187. }
  188. }
  189. }
  190. @CommandMetaData(name = "disable", description = "Disable a plugin")
  191. public static class DisablePlugin extends PluginCommand {
  192. @Argument(index = 0, required = true, metaVar = "<ID>|<INDEX>", usage = "the plugin to disable")
  193. protected String id;
  194. @Override
  195. public void run() throws Failure {
  196. IGitblit gitblit = getContext().getGitblit();
  197. PluginWrapper pluginWrapper = getPlugin(id);
  198. if (pluginWrapper == null) {
  199. throw new UnloggedFailure("Invalid plugin specified!");
  200. }
  201. if (gitblit.disablePlugin(pluginWrapper.getPluginId())) {
  202. stdout.println(String.format("Disabled %s", pluginWrapper.getPluginId()));
  203. } else {
  204. throw new UnloggedFailure(1, String.format("Failed to disable %s", pluginWrapper.getPluginId()));
  205. }
  206. }
  207. }
  208. @CommandMetaData(name = "show", description = "Show the details of a plugin")
  209. public static class ShowPlugin extends PluginCommand {
  210. @Argument(index = 0, required = true, metaVar = "<ID>|<INDEX>", usage = "the plugin to show")
  211. protected String id;
  212. @Override
  213. public void run() throws Failure {
  214. IGitblit gitblit = getContext().getGitblit();
  215. PluginWrapper pw = getPlugin(id);
  216. if (pw == null) {
  217. PluginRegistration registration = gitblit.lookupPlugin(id);
  218. if (registration == null) {
  219. throw new Failure(1, String.format("Unknown plugin %s", id));
  220. }
  221. show(registration);
  222. } else {
  223. show(pw);
  224. }
  225. }
  226. protected String buildFieldTable(PluginWrapper pw, PluginRegistration reg) {
  227. Version system = getContext().getGitblit().getSystemVersion();
  228. PluginRelease current = reg == null ? null : reg.getCurrentRelease(system);
  229. if (current == null) {
  230. current = new PluginRelease();
  231. current.version = "";
  232. current.requires = "";
  233. }
  234. final String id = pw == null ? reg.id : pw.getPluginId();
  235. final String description = reg == null ? pw.getDescriptor().getPluginDescription() : reg.description;
  236. final String version = pw == null ? current.version : pw.getDescriptor().getVersion().toString();
  237. final String requires = pw == null ? current.requires : pw.getDescriptor().getRequires().toString();
  238. final String provider = pw == null ? reg.provider : pw.getDescriptor().getProvider();
  239. final String registry = reg == null ? "" : reg.registry;
  240. final String path = pw == null ? "" : pw.getPluginPath();
  241. final String projectUrl = reg == null ? "" : reg.projectUrl;
  242. final String state;
  243. if (pw == null) {
  244. // plugin could be installed
  245. state = InstallState.NOT_INSTALLED.toString();
  246. } else if (reg == null) {
  247. // unregistered, installed plugin
  248. state = Joiner.on(", ").join(InstallState.INSTALLED, pw.getPluginState());
  249. } else {
  250. // registered, installed plugin
  251. state = Joiner.on(", ").join(reg.getInstallState(), pw.getPluginState());
  252. }
  253. StringBuilder sb = new StringBuilder();
  254. sb.append("ID : ").append(id).append('\n');
  255. sb.append("Version : ").append(version).append('\n');
  256. sb.append("Requires : ").append(requires).append('\n');
  257. sb.append("State : ").append(state).append('\n');
  258. sb.append("Path : ").append(path).append('\n');
  259. sb.append('\n');
  260. sb.append("Description : ").append(description).append('\n');
  261. sb.append("Provider : ").append(provider).append('\n');
  262. sb.append("Project URL : ").append(projectUrl).append('\n');
  263. sb.append("Registry : ").append(registry).append('\n');
  264. return sb.toString();
  265. }
  266. protected String buildReleaseTable(PluginRegistration reg) {
  267. List<PluginRelease> releases = reg.releases;
  268. Collections.sort(releases);
  269. String releaseTable;
  270. if (releases.isEmpty()) {
  271. releaseTable = FlipTable.EMPTY;
  272. } else {
  273. String[] headers = { "Version", "Date", "Requires" };
  274. Object[][] data = new Object[releases.size()][];
  275. for (int i = 0; i < releases.size(); i++) {
  276. PluginRelease release = releases.get(i);
  277. data[i] = new Object[] { (release.version.equals(reg.installedRelease) ? ">" : " ") + release.version,
  278. release.date, release.requires };
  279. }
  280. releaseTable = FlipTable.of(headers, data, Borders.COLS);
  281. }
  282. return releaseTable;
  283. }
  284. /**
  285. * Show an uninstalled plugin.
  286. *
  287. * @param reg
  288. */
  289. protected void show(PluginRegistration reg) {
  290. // REGISTRATION
  291. final String fields = buildFieldTable(null, reg);
  292. final String releases = buildReleaseTable(reg);
  293. String[] headers = { reg.id };
  294. Object[][] data = new Object[3][];
  295. data[0] = new Object[] { fields };
  296. data[1] = new Object[] { "RELEASES" };
  297. data[2] = new Object[] { releases };
  298. stdout.println(FlipTable.of(headers, data));
  299. }
  300. /**
  301. * Show an installed plugin.
  302. *
  303. * @param pw
  304. */
  305. protected void show(PluginWrapper pw) {
  306. IGitblit gitblit = getContext().getGitblit();
  307. PluginRegistration reg = gitblit.lookupPlugin(pw.getPluginId());
  308. // FIELDS
  309. final String fields = buildFieldTable(pw, reg);
  310. // EXTENSIONS
  311. StringBuilder sb = new StringBuilder();
  312. List<Class<?>> exts = gitblit.getExtensionClasses(pw.getPluginId());
  313. String extensions;
  314. if (exts.isEmpty()) {
  315. extensions = FlipTable.EMPTY;
  316. } else {
  317. StringBuilder description = new StringBuilder();
  318. for (int i = 0; i < exts.size(); i++) {
  319. Class<?> ext = exts.get(i);
  320. if (ext.isAnnotationPresent(CommandMetaData.class)) {
  321. CommandMetaData meta = ext.getAnnotation(CommandMetaData.class);
  322. description.append(meta.name());
  323. if (meta.description().length() > 0) {
  324. description.append(": ").append(meta.description());
  325. }
  326. description.append('\n');
  327. }
  328. description.append(ext.getName()).append("\n └ ");
  329. description.append(getExtensionPoint(ext).getName());
  330. description.append("\n\n");
  331. }
  332. extensions = description.toString();
  333. }
  334. // DEPENDENCIES
  335. sb.setLength(0);
  336. List<PluginDependency> deps = pw.getDescriptor().getDependencies();
  337. String dependencies;
  338. if (deps.isEmpty()) {
  339. dependencies = FlipTable.EMPTY;
  340. } else {
  341. String[] headers = { "Id", "Version" };
  342. Object[][] data = new Object[deps.size()][];
  343. for (int i = 0; i < deps.size(); i++) {
  344. PluginDependency dep = deps.get(i);
  345. data[i] = new Object[] { dep.getPluginId(), dep.getPluginVersion() };
  346. }
  347. dependencies = FlipTable.of(headers, data, Borders.COLS);
  348. }
  349. // RELEASES
  350. String releases;
  351. if (reg == null) {
  352. releases = FlipTable.EMPTY;
  353. } else {
  354. releases = buildReleaseTable(reg);
  355. }
  356. String[] headers = { pw.getPluginId() };
  357. Object[][] data = new Object[7][];
  358. data[0] = new Object[] { fields };
  359. data[1] = new Object[] { "EXTENSIONS" };
  360. data[2] = new Object[] { extensions };
  361. data[3] = new Object[] { "DEPENDENCIES" };
  362. data[4] = new Object[] { dependencies };
  363. data[5] = new Object[] { "RELEASES" };
  364. data[6] = new Object[] { releases };
  365. stdout.println(FlipTable.of(headers, data));
  366. }
  367. /* Find the ExtensionPoint */
  368. protected Class<?> getExtensionPoint(Class<?> clazz) {
  369. Class<?> superClass = clazz.getSuperclass();
  370. if (ExtensionPoint.class.isAssignableFrom(superClass)) {
  371. return superClass;
  372. }
  373. return getExtensionPoint(superClass);
  374. }
  375. }
  376. @CommandMetaData(name = "refresh", description = "Refresh the plugin registry data")
  377. public static class RefreshPlugins extends SshCommand {
  378. @Option(name = "--noverify", usage = "Disable checksum verification")
  379. private boolean disableChecksum;
  380. @Override
  381. public void run() throws Failure {
  382. IGitblit gitblit = getContext().getGitblit();
  383. gitblit.refreshRegistry(!disableChecksum);
  384. }
  385. }
  386. @CommandMetaData(name = "available", description = "List the available plugins")
  387. public static class AvailablePlugins extends ListFilterCommand<PluginRegistration> {
  388. @Option(name = "--refresh", aliases = { "-r" }, usage = "refresh the plugin registry")
  389. protected boolean refresh;
  390. @Option(name = "--updates", aliases = { "-u" }, usage = "show available updates")
  391. protected boolean updates;
  392. @Option(name = "--noverify", usage = "Disable checksum verification")
  393. private boolean disableChecksum;
  394. @Override
  395. protected List<PluginRegistration> getItems() throws UnloggedFailure {
  396. IGitblit gitblit = getContext().getGitblit();
  397. if (refresh) {
  398. gitblit.refreshRegistry(!disableChecksum);
  399. }
  400. List<PluginRegistration> list;
  401. if (updates) {
  402. list = gitblit.getRegisteredPlugins(InstallState.UPDATE_AVAILABLE);
  403. } else {
  404. list = gitblit.getRegisteredPlugins();
  405. }
  406. return list;
  407. }
  408. @Override
  409. protected boolean matches(String filter, PluginRegistration t) {
  410. return t.id.matches(filter) || (t.description != null && t.description.matches(filter));
  411. }
  412. @Override
  413. protected void asTable(List<PluginRegistration> list) {
  414. String[] headers;
  415. if (verbose) {
  416. String [] h = { "Id", "Description", "Installed", "Current", "Requires", "State", "Registry" };
  417. headers = h;
  418. } else {
  419. String [] h = { "Id", "Installed", "Current", "Requires", "State" };
  420. headers = h;
  421. }
  422. Version system = getContext().getGitblit().getSystemVersion();
  423. Object[][] data = new Object[list.size()][];
  424. for (int i = 0; i < list.size(); i++) {
  425. PluginRegistration p = list.get(i);
  426. PluginRelease curr = p.getCurrentRelease(system);
  427. if (curr == null) {
  428. curr = new PluginRelease();
  429. }
  430. if (verbose) {
  431. data[i] = new Object[] {p.id, p.description, p.installedRelease, curr.version, curr.requires, p.getInstallState(), p.registry};
  432. } else {
  433. data[i] = new Object[] {p.id, p.installedRelease, curr.version, curr.requires, p.getInstallState()};
  434. }
  435. }
  436. stdout.println(FlipTable.of(headers, data, Borders.BODY_HCOLS));
  437. }
  438. @Override
  439. protected void asTabbed(List<PluginRegistration> list) {
  440. Version system = getContext().getGitblit().getSystemVersion();
  441. for (PluginRegistration p : list) {
  442. PluginRelease curr = p.getCurrentRelease(system);
  443. if (curr == null) {
  444. curr = new PluginRelease();
  445. }
  446. if (verbose) {
  447. outTabbed(p.id, p.description, p.installedRelease, curr.version, curr.requires, p.getInstallState(), p.provider, p.registry);
  448. } else {
  449. outTabbed(p.id, p.installedRelease, curr.version, curr.requires, p.getInstallState());
  450. }
  451. }
  452. }
  453. }
  454. @CommandMetaData(name = "install", description = "Download and installs a plugin")
  455. public static class InstallPlugin extends SshCommand {
  456. @Argument(index = 0, required = true, metaVar = "<URL>|<ID>", usage = "the id or the url of the plugin to download and install")
  457. protected String urlOrId;
  458. @Option(name = "--version", usage = "The specific version to install")
  459. private String version;
  460. @Option(name = "--noverify", usage = "Disable checksum verification")
  461. private boolean disableChecksum;
  462. @Override
  463. public void run() throws Failure {
  464. IGitblit gitblit = getContext().getGitblit();
  465. try {
  466. String ulc = urlOrId.toLowerCase();
  467. if (ulc.startsWith("http://") || ulc.startsWith("https://")) {
  468. if (gitblit.installPlugin(urlOrId, !disableChecksum)) {
  469. stdout.println(String.format("Installed %s", urlOrId));
  470. } else {
  471. throw new UnloggedFailure(1, String.format("Failed to install %s", urlOrId));
  472. }
  473. } else {
  474. PluginRelease pr = gitblit.lookupRelease(urlOrId, version);
  475. if (pr == null) {
  476. throw new UnloggedFailure(1, String.format("Plugin \"%s\" is not in the registry!", urlOrId));
  477. }
  478. // enforce minimum system requirement
  479. if (!StringUtils.isEmpty(pr.requires)) {
  480. Version requires = Version.createVersion(pr.requires);
  481. Version system = gitblit.getSystemVersion();
  482. boolean isValid = system.isZero() || system.atLeast(requires);
  483. if (!isValid) {
  484. String msg = String.format("Plugin \"%s:%s\" requires Gitblit %s",
  485. urlOrId, pr.version, pr.requires);
  486. throw new UnloggedFailure(1, msg);
  487. }
  488. }
  489. if (gitblit.installPlugin(pr.url, !disableChecksum)) {
  490. stdout.println(String.format("Installed %s", urlOrId));
  491. } else {
  492. throw new UnloggedFailure(1, String.format("Failed to install %s", urlOrId));
  493. }
  494. }
  495. } catch (IOException e) {
  496. log.error("Failed to install " + urlOrId, e);
  497. throw new UnloggedFailure(1, String.format("Failed to install %s", urlOrId), e);
  498. }
  499. }
  500. }
  501. @CommandMetaData(name = "upgrade", description = "Upgrade a plugin")
  502. public static class UpgradePlugin extends PluginCommand {
  503. @Argument(index = 0, required = true, metaVar = "<ID>|<INDEX>", usage = "the plugin to upgrade")
  504. protected String id;
  505. @Option(name = "--version", usage = "The specific version to install")
  506. private String version;
  507. @Option(name = "--noverify", usage = "Disable checksum verification")
  508. private boolean disableChecksum;
  509. @Override
  510. public void run() throws Failure {
  511. IGitblit gitblit = getContext().getGitblit();
  512. PluginWrapper pluginWrapper = getPlugin(id);
  513. if (pluginWrapper == null) {
  514. throw new UnloggedFailure("Invalid plugin specified!");
  515. }
  516. PluginRelease pr = gitblit.lookupRelease(pluginWrapper.getPluginId(), version);
  517. if (pr == null) {
  518. throw new UnloggedFailure(1, String.format("Plugin \"%s\" is not in the registry!", pluginWrapper.getPluginId()));
  519. }
  520. // enforce minimum system requirement
  521. if (!StringUtils.isEmpty(pr.requires)) {
  522. Version requires = Version.createVersion(pr.requires);
  523. Version system = gitblit.getSystemVersion();
  524. boolean isValid = system.isZero() || system.atLeast(requires);
  525. if (!isValid) {
  526. throw new Failure(1, String.format("Plugin \"%s:%s\" requires Gitblit %s",
  527. pluginWrapper.getPluginId(), pr.version, pr.requires));
  528. }
  529. }
  530. try {
  531. if (gitblit.upgradePlugin(pluginWrapper.getPluginId(), pr.url, !disableChecksum)) {
  532. stdout.println(String.format("Upgraded %s", pluginWrapper.getPluginId()));
  533. } else {
  534. throw new UnloggedFailure(1, String.format("Failed to upgrade %s", pluginWrapper.getPluginId()));
  535. }
  536. } catch (IOException e) {
  537. log.error("Failed to upgrade " + pluginWrapper.getPluginId(), e);
  538. throw new UnloggedFailure(1, String.format("Failed to upgrade %s", pluginWrapper.getPluginId()), e);
  539. }
  540. }
  541. }
  542. @CommandMetaData(name = "uninstall", aliases = { "rm", "del" }, description = "Uninstall a plugin")
  543. public static class UninstallPlugin extends PluginCommand {
  544. @Argument(index = 0, required = true, metaVar = "<ID>|<INDEX>", usage = "the plugin to uninstall")
  545. protected String id;
  546. @Override
  547. public void run() throws Failure {
  548. IGitblit gitblit = getContext().getGitblit();
  549. PluginWrapper pluginWrapper = getPlugin(id);
  550. if (pluginWrapper == null) {
  551. throw new UnloggedFailure(String.format("Plugin %s is not installed!", id));
  552. }
  553. if (gitblit.uninstallPlugin(pluginWrapper.getPluginId())) {
  554. stdout.println(String.format("Uninstalled %s", pluginWrapper.getPluginId()));
  555. } else {
  556. throw new UnloggedFailure(1, String.format("Failed to uninstall %s", pluginWrapper.getPluginId()));
  557. }
  558. }
  559. }
  560. }