diff --git a/build/fbcode_builder/getdeps.py b/build/fbcode_builder/getdeps.py index f9ba16216..53396faf1 100755 --- a/build/fbcode_builder/getdeps.py +++ b/build/fbcode_builder/getdeps.py @@ -71,6 +71,23 @@ class ShowHostType(SubCmd): class ProjectCmdBase(SubCmd): def run(self, args): opts = setup_build_options(args) + + if args.current_project is not None: + opts.repo_project = args.current_project + if args.project is None: + if opts.repo_project is None: + raise UsageError( + "no project name specified, and no .projectid file found" + ) + if opts.repo_project == "fbsource": + # The fbsource repository is a little special. There is no project + # manifest file for it. A specific project must always be explicitly + # specified when building from fbsource. + raise UsageError( + "no project name specified (required when building in fbsource)" + ) + args.project = opts.repo_project + ctx_gen = opts.get_context_generator(facebook_internal=args.facebook_internal) if args.test_dependencies: ctx_gen.set_value_for_all_projects("test", "on") @@ -101,6 +118,12 @@ class ProjectCmdBase(SubCmd): return project, os.path.abspath(path) + # If we are currently running from a project repository, + # use the current repository for the project sources. + build_opts = loader.build_opts + if build_opts.repo_project is not None and build_opts.repo_root is not None: + loader.set_project_src_dir(build_opts.repo_project, build_opts.repo_root) + for arg in args.src_dir: project, path = parse_project_arg(arg, "--src-dir") loader.set_project_src_dir(project, path) @@ -116,6 +139,7 @@ class ProjectCmdBase(SubCmd): def setup_parser(self, parser): parser.add_argument( "project", + nargs="?", help=( "name of the project or path to a manifest " "file describing the project" @@ -133,6 +157,12 @@ class ProjectCmdBase(SubCmd): action="store_true", help="Enable building tests for dependencies as well.", ) + parser.add_argument( + "--current-project", + help="Specify the name of the fbcode_builder manifest file for the " + "current repository. If not specified, the code will attempt to find " + "this in a .projectid file in the repository root.", + ) parser.add_argument( "--src-dir", default=[], diff --git a/build/fbcode_builder/getdeps/buildopts.py b/build/fbcode_builder/getdeps/buildopts.py index e730cd613..910361ce7 100644 --- a/build/fbcode_builder/getdeps/buildopts.py +++ b/build/fbcode_builder/getdeps/buildopts.py @@ -35,10 +35,28 @@ def containing_repo_type(path): parent = os.path.dirname(path) if parent == path: - return None + return None, None path = parent +def detect_project(path): + repo_type, repo_root = containing_repo_type(path) + if repo_type is None: + return None, None + + # Look for a .projectid file. If it exists, read the project name from it. + project_id_path = os.path.join(repo_root, ".projectid") + try: + with open(project_id_path, "r") as f: + project_name = f.read().strip() + return repo_root, project_name + except EnvironmentError as ex: + if ex.errno != errno.ENOENT: + raise + + return repo_root, None + + class BuildOptions(object): def __init__( self, @@ -78,11 +96,13 @@ class BuildOptions(object): self.project_hashes = hashes break - # Use a simplistic heuristic to figure out if we're in fbsource - # and where the root of fbsource can be found - repo_type, repo_root = containing_repo_type(fbcode_builder_dir) - if repo_type == "hg": - self.fbsource_dir = repo_root + # Detect what repository and project we are being run from. + self.repo_root, self.repo_project = detect_project(os.getcwd()) + + # If we are running from an fbsource repository, set self.fbsource_dir + # to allow the ShipIt-based fetchers to use it. + if self.repo_project == "fbsource": + self.fbsource_dir = self.repo_root else: self.fbsource_dir = None