def run_command(command, command_args, options):
  '''Handle command-line invocation.'''

  cwd = os.getcwd()

  if command in _COMMAND_ABBREVS:
    command = _COMMAND_ABBREVS[command]

  config = Config(options=options)

  if options.scope:
    options.scope = options.scope.rstrip('/')

  def populate_options_from_cwd(cwd, options):
    # Get fallback values for root_uri and scope settings from cwd, but only
    # use them if we don't have them already provided.
    (cwd_work, cwd_rel_path, cwd_scope) = WorkingDir.work_dir_context_for_path(cwd, config)
    cwd_work_dir = cwd_work.work_dir if cwd_work else None
    cwd_root_uri = cwd_work.config.root_uri if cwd_work else None
    if options.root_uri and cwd_root_uri and cwd_root_uri != options.root_uri:
      fail("something is wrong: configured root URI '%s' does not match provided root URI '%s'" % (cwd_root_uri, options.root_uri))
    if not options.root_uri and cwd_root_uri:
      options.root_uri = cwd_root_uri
    if not options.scope and cwd_scope:
      options.scope = cwd_scope
    if not options.work_dir and cwd_work_dir:
      options.work_dir = cwd_work_dir

  if command in _COMMAND_LIST_REPO:
    if command == "init":
      options.root_uri = require_arg(command, 1, "root_uri", command_args)
      repo = Repo(options.root_uri, config, check_valid=False)
      repo.init_repo()
    else:
      populate_options_from_cwd(cwd, options)
      require_opt(command, "root_uri", options)
      repo = Repo(options.root_uri, config, check_valid=True)
      if command == "newscope":
        scope = require_arg(command, 1, "scope", command_args).rstrip('/')
        require_opt(command, "user", options)
        commit_time = parse_datetime(options.date) if options.date else None
        repo.create_scope(scope, user=options.user, message=options.message, time=commit_time)
      if command == "scopes":
        scopes = repo.get_scopes()
        for scope in scopes:
          print "%s" % scope
      elif command == "log":
        require_opt(command, "scope", options)
        (start, end) = determine_rev_range(options, config)
        time_filter = parse_datespec(options.date, assume_utc=options.assume_utc) if options.date else None
        filter = (lambda mf: time_filter(mf.time)) if time_filter else None
        repo.log(options.scope, sys.stdout, srev_start=start, srev_end=end, filter=filter)
      elif command == "tag":
        # Tag command doesn't require a repository, but if we have one, it's
        # needed to identify checked out tip (for default revisions)
        work = None
        if options.work_dir:
          log.debug("using working dir for tag command revs: %s", options.work_dir)
          work = WorkingDir(options.work_dir, config)
        tag_name = require_arg(command, 1, "tag name", command_args)
        if options.all:
          raise InvalidOperation("tag --all doesn't make much sense and is not supported")
        if options.work:
          if options.rev:
            raise InvalidOperation("cannot tag specific revision with --work option")
          if not work:
            raise InvalidOperation("must have working directory for 'tag --work'")

          checkouts = work.checkouts()
          for checkout in checkouts:
            log.info("tagging scope '%s' with tag '%s' at revision %s", checkout.scope, tag_name, checkout.rev)
            repo.tag(checkout.scope, tag_name, checkout.rev)
        else:
          require_opt(command, "scope", options)
          if not options.rev and work:
            rev = work.get_checkout_rev(options.scope)
          else:
            # Make sure revision is explicit: we don't want to tag against tip, since it's not well defined.
            # Using "-r tip" will still force.
            require_opt(command, "rev", options)
            rev = options.rev
          log.info("tagging scope '%s' with tag '%s' at revision %s", options.scope, tag_name, rev)
          repo.tag(options.scope, tag_name, rev)
      elif command == "tags":
        require_opt(command, "scope", options)
        (start, end) = parse_rev_range(options.rev) if options.rev else ("tip", None)
        time_filter = parse_datespec(options.date, assume_utc=options.assume_utc) if options.date else None
        filter = (lambda mf: time_filter(mf.time)) if time_filter else None
        tags = repo.get_tags(options.scope, srev_start=start, srev_end=end, filter=filter)
        for (name, rev) in tags:
          print "%s\t%s" % (name, rev)
      elif command == "list":
        require_opt(command, "scope", options)
        rev = options.rev if options.rev else "tip"
        path = command_args[0] if len(command_args) > 0 else ""
        items = repo.list(options.scope, path, rev, recursive=options.recursive)
        prefix = None if options.short_paths else options.scope
        for item in items:
          print item.display_path(prefix=prefix)
      elif command == "locate":
        # TODO Rename to _locate and also include compression scheme in output.
        require_opt(command, "scope", options)
        rev = options.rev if options.rev else "tip"
        path = command_args[0] if len(command_args) > 0 else ""
        items = repo.locate(options.scope, path, rev, recursive=options.recursive)
        for item in items:
          print "%s\t%s" % (item[0], item[1])
      elif command == "copy":
        require_opt(command, "scope", options)
        rev = options.rev if options.rev else "tip"
        src_path = require_arg(command, 1, "source path", command_args)
        target_path = require_arg(command, 2, "target path", command_args)
        repo.copy(options.scope, src_path, rev, target_path, clobber=options.force, recursive=options.recursive)
      elif command == "_manifest":
        require_opt(command, "scope", options)
        rev = options.rev if options.rev else "tip"
        mf = repo.get_manifest(options.scope, rev)
        print mf.to_str()

  elif command in _COMMAND_LIST_WORK:

    # check the mode option
    if options.mode is not None:
      options.mode = options.mode.lower()
      if options.mode not in Mode.values():
        raise InvalidArgument("--mode has to be one of %s" % Mode.values())

    # Set up a new working dir, if necessary. Do this now so we can create a WorkingDir object.
    if command == "checkout":
      rev = options.rev if options.rev else "tip"
      options.root_uri = require_arg(command, 1, "root URI", command_args)
      options.work_dir = command_args[1] if len(command_args) > 1 else cwd
      if not options.all:
        # Validate all arguments are right _before_ mutating working directory
        require_opt(command, "scope", options)
        Repo(options.root_uri, config, check_valid=True).resolve_rev(options.scope, rev)
      first_time = WorkingDir.initialize_work_dir(options.work_dir, options.root_uri)
      if first_time:
        log.info("initialized new working directory at: %s", options.work_dir)
      work = WorkingDir(options.work_dir, config)
      if options.all:
        if rev != "tip":
          raise InvalidArgument("can only check out with --all using tip revision")
        scopes = work.repo.get_scopes()
        if len(scopes) < 1:
          raise InvalidOperation("no scopes found", suppressable=True)
        log.info("checking out %d scopes", len(scopes))
        for scope in scopes:
          work.checkout(scope, rev, force=options.force, mode=options.mode)
      else:
        require_opt(command, "scope", options)
        work.checkout(options.scope, rev, force=options.force, mode=options.mode)
    else:
      populate_options_from_cwd(cwd, options)
      work = WorkingDir(options.work_dir, config)

      if command == "id":
        require_opt(command, "scope", options)
        rev = work.get_checkout_rev(options.scope)
        if not rev:
          raise InvalidOperation("scope '%s' is not checked out" % options.scope)
        print "%s" % rev
      elif command == "ids":
        checkouts = work.checkouts()
        for checkout in checkouts:
          print "%s\t%s" % (checkout.scope, checkout.rev)
      elif command == "status":
        if options.all:
          raise InvalidOperation("status --all doesn't make much sense; try status --work instead")
        elif options.work:
          checkouts = work.checkouts()
          for checkout in checkouts:
            prefix = None if options.short_paths else checkout.scope
            sys.stdout.write(work.status(checkout.scope, mod_all=options.mod_all, full=options.full).to_summary(prefix=prefix))
        else:
          require_opt(command, "scope", options)
          log.debug("status for scope '%s'", options.scope)
          prefix = None if options.short_paths else options.scope
          sys.stdout.write(work.status(options.scope, mod_all=options.mod_all, full=options.full).to_summary(prefix=prefix))
      elif command == "commit":
        if options.mode is not None:
          raise InvalidOperation("%s --mode is not allowed; use track/untrack commands first" % command)
        require_opt(command, "user", options)
        require_opt(command, "message", options)
        commit_time = parse_datetime(options.date, assume_utc=options.assume_utc) if options.date else None
        if options.all:
          raise InvalidOperation("commit --all doesn't make much sense; try commit --work instead")
        elif options.work:
          checkouts = work.checkouts()
          for checkout in checkouts:
            log.info("committing scope '%s'", checkout.scope)
            work.commit(checkout.scope, user=options.user, message=options.message, time=commit_time, empty_ok=True, mod_all=options.mod_all)
        else:
          require_opt(command, "scope", options)
          work.commit(options.scope, user=options.user, message=options.message, time=commit_time, mod_all=options.mod_all)
      elif command == "update":
        rev = options.rev if options.rev else "tip"
        if not options.all and not options.work:
          require_opt(command, "scope", options)
          work.update(options.scope, rev, force=options.force)
        else:
          # For --work or --all, first update all known scopes
          if rev != "tip":
            raise InvalidArgument("can only update with --all or --work using tip revision")
          checkouts = work.checkouts()
          scopes_to_checkout = None
          if options.work:
            log.info("updating %d scopes", len(checkouts))
          else:
            # update --all: also do a checkout on other new scopes
            scopes_checked_out = set(checkout.scope for checkout in checkouts)
            scopes_to_checkout = [scope for scope in work.repo.get_scopes() if scope not in scopes_checked_out]
            log.info("updating %d scopes and checking out %d new scopes", len(scopes_checked_out), len(scopes_to_checkout))
          for checkout in checkouts:
            work.update(checkout.scope, rev, force=options.force)
          if scopes_to_checkout:
            for scope in scopes_to_checkout:
              work.checkout(scope, rev, force=options.force, mode=options.mode)
      elif command == "revert":
        if options.mode is not None:
          raise InvalidOperation("%s --mode is not allowed; use track/untrack commands first" % command)
        if options.all:
          raise InvalidOperation("revert --all doesn't make much sense; try commit --work instead")
        elif options.rev:
          raise NotImplementedError("sorry, revert to specified revision not yet implemented")
        elif options.work:
          checkouts = work.checkouts()
          if len(command_args) > 0:
            raise InvalidOperation("revert --work takes no arguments")
          for checkout in checkouts:
            log.info("reverting scope '%s'", checkout.scope)
            work.revert(checkout.scope)
        else:
          # TODO support revert to specified revision
          require_opt(command, "scope", options)
          work.revert(options.scope, path_list=command_args)
      elif command in ["track", "untrack"]:
        if options.all:
          raise InvalidOperation("%s --all doesn't make much sense; try --work instead" % command)
        elif options.rev:
          raise NotImplementedError("sorry, %s to specified revision not yet implemented" % command)
        elif (options.mode is None and not command_args) or (options.mode == Mode.AUTO and (command == "untrack" or (command == "track" and len(command_args) > 0))):
          raise InvalidOperation("%s doesn't make much sense" % " ".join([command, "--mode " + options.mode if options.mode else ""] + command_args))
        elif options.force:
          raise InvalidOperation("do not use force option with %s command" % command)
        elif options.work:
          checkouts = work.checkouts()
        else:
          require_opt(command, "scope", options)
          checkouts = [Checkout(options.scope, work.get_checkout_rev(options.scope), None)]
        if command == "track":
          if len(command_args) > 0:
            # track some files
            for checkout in checkouts:
              work.track(checkout.scope, track_path_list=command_args, mode=options.mode, no_download=options.no_download, recursive=options.recursive)
          else:
            # Change mode
            for checkout in checkouts:
              work.track(checkout.scope, mode=options.mode, no_download=options.no_download, recursive=options.recursive)
        elif command == "untrack":
          # untrack some files
          for checkout in checkouts:
            work.untrack(checkout.scope, command_args, options.mode, recursive=options.recursive)
        else:
          assert False
      elif command == "diff":
        if options.all or options.date or options.mod_all or options.no_cache or options.work:
          raise InvalidOperation("diff --all --date --mod-all --no-cache --work are not supported")
        elif options.short_paths:
          raise NotImplementedError("sorry, diff --short-paths not yet implemented")
        else:
          require_opt(command, "scope", options)
          work.diff(options.scope, options.rev, path_list=command_args)
  else:
    assert False
dataset/ETHPy150Open bloomreach/zinc/zinc.py/run_command/original