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.

144 lines
4.2 KiB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from __future__ import print_function
  4. import ast
  5. import os
  6. import sys
  7. from argparse import ArgumentParser
  8. from subprocess import check_call
  9. from doodbalib import (
  10. CORE,
  11. ENTERPRISE,
  12. MANIFESTS,
  13. PRIVATE,
  14. SRC_DIR,
  15. AddonsConfigError,
  16. addons_config,
  17. logger,
  18. )
  19. # Exit codes
  20. EXIT_NO_ADDONS = 0x4
  21. # Define CLI options
  22. parser = ArgumentParser(description="Install addons in current environment")
  23. parser.add_argument(
  24. "action",
  25. choices=("init", "update", "list"),
  26. help="What to do with the matched addons.",
  27. )
  28. parser.add_argument(
  29. "-c", "--core", action="store_true", help="Use all Odoo core addons"
  30. )
  31. parser.add_argument(
  32. "-d",
  33. "--dependencies",
  34. action="store_true",
  35. help="Use only dependencies of selected addons",
  36. )
  37. parser.add_argument("-e", "--extra", action="store_true", help="Use all extra addons")
  38. parser.add_argument(
  39. "-f",
  40. "--fullpath",
  41. action="store_true",
  42. help="Print addon's full path, only useful with list mode",
  43. )
  44. parser.add_argument(
  45. "-i", "--installable", action="store_true", help="Include only installable addons"
  46. )
  47. parser.add_argument(
  48. "-n", "--enterprise", action="store_true", help="Use all enterprise addons"
  49. )
  50. parser.add_argument(
  51. "-p", "--private", action="store_true", help="Use all private addons"
  52. )
  53. parser.add_argument(
  54. "-s",
  55. "--separator",
  56. type=str,
  57. default=",",
  58. help="String that separates addons only useful with list mode",
  59. )
  60. parser.add_argument(
  61. "-t",
  62. "--test",
  63. action="store_true",
  64. help="Run unit tests for these addons, usually combined with update",
  65. )
  66. parser.add_argument(
  67. "-x",
  68. "--explicit",
  69. action="store_true",
  70. help="Fail if any addon is explicitly declared but not found",
  71. )
  72. parser.add_argument(
  73. "-w",
  74. "--with",
  75. action="append",
  76. dest="with_",
  77. default=[],
  78. help="Addons to include always.",
  79. )
  80. parser.add_argument(
  81. "-W", "--without", action="append", default=[], help="Addons to exclude always."
  82. )
  83. # Generate the matching addons set
  84. args = parser.parse_args()
  85. dependencies = {"base"}
  86. addons = set(args.with_)
  87. without = set(args.without)
  88. if addons & without:
  89. sys.exit("Cannot include and exclude the same addon!")
  90. if args.dependencies and args.fullpath:
  91. sys.exit("Unsupported combination of --dependencies and --fullpath")
  92. try:
  93. for addon, repo in addons_config(strict=args.explicit):
  94. if addon in without:
  95. continue
  96. core_ok = args.core and repo == CORE
  97. enterprise_ok = args.enterprise and repo == ENTERPRISE
  98. extra_ok = args.extra and repo not in {CORE, ENTERPRISE, PRIVATE}
  99. private_ok = args.private and repo == PRIVATE
  100. manual_ok = addon in addons
  101. if private_ok or core_ok or extra_ok or enterprise_ok or manual_ok:
  102. addon_path = os.path.join(SRC_DIR, repo, addon)
  103. manifest = {}
  104. for manifest_name in MANIFESTS:
  105. try:
  106. manifest_path = os.path.join(addon_path, manifest_name)
  107. with open(manifest_path, "r") as code:
  108. manifest = ast.literal_eval(code.read())
  109. break
  110. except IOError:
  111. continue
  112. if args.installable and not manifest.get("installable", True):
  113. continue
  114. dependencies.update(manifest.get("depends", []))
  115. if args.fullpath and args.action == "list":
  116. addon = addon_path
  117. addons.add(addon)
  118. except AddonsConfigError as error:
  119. sys.exit(error.message)
  120. # Use dependencies instead, if requested
  121. if args.dependencies:
  122. addons = dependencies - addons
  123. addons -= without
  124. # Do the required action
  125. if not addons:
  126. print("No addons found", file=sys.stderr)
  127. sys.exit(EXIT_NO_ADDONS)
  128. addons = args.separator.join(sorted(addons))
  129. if args.action == "list":
  130. print(addons)
  131. else:
  132. command = ["odoo", "--stop-after-init", "--{}".format(args.action), addons]
  133. if args.test:
  134. command += ["--test-enable", "--workers", "0"]
  135. if os.environ.get("PGDATABASE"):
  136. command += ["--db-filter", u"^{}$".format(os.environ.get("PGDATABASE"))]
  137. logger.info("Executing %s", " ".join(command))
  138. check_call(command)