public static function newAPIFromWorkingCopyIdentity(ArcanistWorkingCopyIdentity $working_copy)
 {
     $root = $working_copy->getProjectRoot();
     if (!$root) {
         throw new ArcanistUsageException("There is no readable '.arcconfig' file in the working directory or " . "any parent directory. Create an '.arcconfig' file to configure arc.");
     }
     // check if we're in an svn working copy
     list($err) = exec_manual('svn info');
     if (!$err) {
         $api = newv('ArcanistSubversionAPI', array($root));
         $api->workingCopyIdentity = $working_copy;
         return $api;
     }
     if (Filesystem::pathExists($root . '/.hg')) {
         $api = newv('ArcanistMercurialAPI', array($root));
         $api->workingCopyIdentity = $working_copy;
         return $api;
     }
     $git_root = self::discoverGitBaseDirectory($root);
     if ($git_root) {
         if (!Filesystem::pathsAreEquivalent($root, $git_root)) {
             throw new ArcanistUsageException("'.arcconfig' file is located at '{$root}', but working copy root " . "is '{$git_root}'. Move '.arcconfig' file to the working copy root.");
         }
         $api = newv('ArcanistGitAPI', array($root));
         $api->workingCopyIdentity = $working_copy;
         return $api;
     }
     throw new ArcanistUsageException("The current working directory is not part of a working copy for a " . "supported version control system (svn, git or mercurial).");
 }
示例#2
0
/**
 * NOTE: SPOOKY BLACK MAGIC
 *
 * When arc is run in a copy of arcanist other than itself, or a copy of
 * libphutil other than the one we loaded, reenter the script and force it
 * to use the current working directory instead of the default.
 *
 * In the case of execution inside arcanist/, we force execution of the local
 * arc binary.
 *
 * In the case of execution inside libphutil/, we force the local copy to load
 * instead of the one selected by default rules.
 *
 * @param PhutilConsole                 Console.
 * @param ArcanistWorkingCopyIdentity   The current working copy.
 * @param array                         Original arc arguments.
 * @return void
 */
function reenter_if_this_is_arcanist_or_libphutil(PhutilConsole $console, ArcanistWorkingCopyIdentity $working_copy, array $original_argv)
{
    $project_id = $working_copy->getProjectID();
    if ($project_id != 'arcanist' && $project_id != 'libphutil') {
        // We're not in a copy of arcanist or libphutil.
        return;
    }
    $library_names = array('arcanist' => 'arcanist', 'libphutil' => 'phutil');
    $library_root = phutil_get_library_root($library_names[$project_id]);
    $project_root = $working_copy->getProjectRoot();
    if (Filesystem::isDescendant($library_root, $project_root)) {
        // We're in a copy of arcanist or libphutil, but already loaded the correct
        // copy. Continue execution normally.
        return;
    }
    if ($project_id == 'libphutil') {
        $console->writeLog("This is libphutil! Forcing this copy to load...\n");
        $original_argv[0] = dirname(phutil_get_library_root('arcanist')) . '/bin/arc';
        $libphutil_path = $project_root;
    } else {
        $console->writeLog("This is arcanist! Forcing this copy to run...\n");
        $original_argv[0] = $project_root . '/bin/arc';
        $libphutil_path = dirname(phutil_get_library_root('phutil'));
    }
    if (phutil_is_windows()) {
        $err = phutil_passthru('set ARC_PHUTIL_PATH=%s & %Ls', $libphutil_path, $original_argv);
    } else {
        $err = phutil_passthru('ARC_PHUTIL_PATH=%s %Ls', $libphutil_path, $original_argv);
    }
    exit($err);
}
示例#3
0
function arcanist_load_libraries($load, $must_load, $lib_source, ArcanistWorkingCopyIdentity $working_copy, $config_trace_mode)
{
    if (!$load) {
        return;
    }
    if (!is_array($load)) {
        $error = "Libraries specified by {$lib_source} are invalid; expected " . "a list. Check your configuration.";
        $console = PhutilConsole::getConsole();
        $console->writeErr("WARNING: %s\n", $error);
        return;
    }
    foreach ($load as $location) {
        // Try to resolve the library location. We look in several places, in
        // order:
        //
        //  1. Inside the working copy. This is for phutil libraries within the
        //     project. For instance "library/src" will resolve to
        //     "./library/src" if it exists.
        //  2. In the same directory as the working copy. This allows you to
        //     check out a library alongside a working copy and reference it.
        //     If we haven't resolved yet, "library/src" will try to resolve to
        //     "../library/src" if it exists.
        //  3. Using normal libphutil resolution rules. Generally, this means
        //     that it checks for libraries next to libphutil, then libraries
        //     in the PHP include_path.
        //
        // Note that absolute paths will just resolve absolutely through rule (1).
        $resolved = false;
        // Check inside the working copy. This also checks absolute paths, since
        // they'll resolve absolute and just ignore the project root.
        $resolved_location = Filesystem::resolvePath($location, $working_copy->getProjectRoot());
        if (Filesystem::pathExists($resolved_location)) {
            $location = $resolved_location;
            $resolved = true;
        }
        // If we didn't find anything, check alongside the working copy.
        if (!$resolved) {
            $resolved_location = Filesystem::resolvePath($location, dirname($working_copy->getProjectRoot()));
            if (Filesystem::pathExists($resolved_location)) {
                $location = $resolved_location;
                $resolved = true;
            }
        }
        if ($config_trace_mode) {
            echo "Loading phutil library from '{$location}'...\n";
        }
        $error = null;
        try {
            phutil_load_library($location);
        } catch (PhutilBootloaderException $ex) {
            $error = "Failed to load phutil library at location '{$location}'. " . "This library is specified by {$lib_source}. Check that the " . "setting is correct and the library is located in the right " . "place.";
            if ($must_load) {
                throw new ArcanistUsageException($error);
            } else {
                file_put_contents('php://stderr', phutil_console_wrap('WARNING: ' . $error . "\n\n"));
            }
        } catch (PhutilLibraryConflictException $ex) {
            if ($ex->getLibrary() != 'arcanist') {
                throw $ex;
            }
            $arc_dir = dirname(dirname(__FILE__));
            $error = "You are trying to run one copy of Arcanist on another copy of " . "Arcanist. This operation is not supported. To execute Arcanist " . "operations against this working copy, run './bin/arc' (from the " . "current working copy) not some other copy of 'arc' (you ran one " . "from '{$arc_dir}').";
            throw new ArcanistUsageException($error);
        }
    }
}