{"action":"created","issue":{"url":"https://api.github.com/repos/guyzmo/git-repo/issues/28","repository_url":"https://api.github.com/repos/guyzmo/git-repo","labels_url":"https://api.github.com/repos/guyzmo/git-repo/issues/28/labels{/name}","comments_url":"https://api.github.com/repos/guyzmo/git-repo/issues/28/comments","events_url":"https://api.github.com/repos/guyzmo/git-repo/issues/28/events","html_url":"https://github.com/guyzmo/git-repo/issues/28","id":158906066,"number":28,"title":"Food for thought: v2 redesign","user":{"login":"guyzmo","id":254441,"avatar_url":"https://avatars.githubusercontent.com/u/254441?v=3","gravatar_id":"","url":"https://api.github.com/users/guyzmo","html_url":"https://github.com/guyzmo","followers_url":"https://api.github.com/users/guyzmo/followers","following_url":"https://api.github.com/users/guyzmo/following{/other_user}","gists_url":"https://api.github.com/users/guyzmo/gists{/gist_id}","starred_url":"https://api.github.com/users/guyzmo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/guyzmo/subscriptions","organizations_url":"https://api.github.com/users/guyzmo/orgs","repos_url":"https://api.github.com/users/guyzmo/repos","events_url":"https://api.github.com/users/guyzmo/events{/privacy}","received_events_url":"https://api.github.com/users/guyzmo/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/guyzmo/git-repo/labels/design","name":"design","color":"fef2c0"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/guyzmo/git-repo/milestones/6","html_url":"https://github.com/guyzmo/git-repo/milestones/2.0","labels_url":"https://api.github.com/repos/guyzmo/git-repo/milestones/6/labels","id":1813254,"number":6,"title":"2.0","description":"Redesign of the API and refactoring of the internals.","creator":{"login":"guyzmo","id":254441,"avatar_url":"https://avatars.githubusercontent.com/u/254441?v=3","gravatar_id":"","url":"https://api.github.com/users/guyzmo","html_url":"https://github.com/guyzmo","followers_url":"https://api.github.com/users/guyzmo/followers","following_url":"https://api.github.com/users/guyzmo/following{/other_user}","gists_url":"https://api.github.com/users/guyzmo/gists{/gist_id}","starred_url":"https://api.github.com/users/guyzmo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/guyzmo/subscriptions","organizations_url":"https://api.github.com/users/guyzmo/orgs","repos_url":"https://api.github.com/users/guyzmo/repos","events_url":"https://api.github.com/users/guyzmo/events{/privacy}","received_events_url":"https://api.github.com/users/guyzmo/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":0,"state":"open","created_at":"2016-06-07T12:03:31Z","updated_at":"2016-06-07T12:04:22Z","due_on":null,"closed_at":null},"comments":0,"created_at":"2016-06-07T12:04:13Z","updated_at":"2016-06-22T20:15:24Z","closed_at":null,"body":"Current code offers a clean and easy to implement API. But as more features gets integrated, the more the help page becomes cluttered. So a redesign of the code would be a good idea to think about.\r\n\r\nAlso, integrating new services means sensitively increasing the code base. Not everybody wants to use all existing services at once, and implementing new services shouldn't be tied to the main code base: if you want to implement support for Gogs (for example) you shouldn't ask for my permission (by doing fork+PR)!\r\n\r\nSo the main things I'm thinking to change for a possible V2 redesign are modularizing the CLI API, and extracting the services as external plugins.\r\n\r\n## Subcommands for the CLI API\r\n\r\nSo the goal would be to modularize the code for each subcommand, so that each feature comes as an independent module coming with its own help page. \r\n\r\nAs currently, each service lies in its own module, that would mean implementing a \"two axis\" modularization: for each service and for each command. Then the main help page would have to be generated and the output would look like:\r\n\r\n```\r\nUsage:\r\n    git-repo [--path=<path>] [-v...] <target> <command> [options]\r\n\r\nOptions:\r\n    <target>            service to use, using the alias (hub, lab or bb),\r\n    <command>           command to trigger, use --help on that command to see usage.\r\n    --path              repository to use\r\n\r\nCommands:\r\n    fork                 Fork a project\r\n    create               Create a new project on the service\r\n    delete               Delete an existing project from the service\r\n    open                 Open the project's page with your browser\r\n    gist                 Manage gists\r\n    request              Manage requests\r\n\r\n```\r\n\r\nThe best way to do that, would be to have for each feature a module and class following this template:\r\n\r\n````\r\n'''\r\ngit-repo : Manage gists from the service \r\n\r\nUsage:\r\n    gist (list|ls) [<gist>]\r\n    gist clone <gist>\r\n    gist fetch <gist> [<gist_file>]\r\n    gist create [--secret] <description> [<gist_path> <gist_path>...]\r\n    gist delete <gist> [-f]\r\n\r\nCommands:\r\n    ...\r\n'''\r\n\r\n@register_interface\r\nclass RepositoryServiceClone:\r\n    def get_service(self, lookup_repository):\r\n        raise NotImplementedError\r\n\r\n    def clone(self, user, repo, branch):\r\n        raise NotImplementedError\r\n\r\n@register_command('clone', __doc__)\r\nclass GitRepoCommandClone:\r\n    def do_clone(self):\r\n        service = self.get_service(lookup_repository=False)\r\n        repo_path = os.path.join(self.path, self.repo_name)\r\n        if os.path.exists(repo_path):\r\n            raise FileExistsError('Cannot clone repository, '\r\n                                  'a folder named {} already exists!'.format(repo_path))\r\n        repository = Repo.init(repo_path)\r\n        service = RepositoryService.get_service(repository, self.target)\r\n        service.clone(self.user_name, self.repo_name, self.branch)\r\n        log.info('Successfully cloned `{}` into `{}`!'.format(\r\n            service.format_path(self.repo_slug),\r\n            repo_path)\r\n        )\r\n        return 0\r\n```\r\n\r\nThen, each service would inherit from each interface offered by a _command_, raising `NotImplementedError` exceptions when it does not offer an implementation. All missing implementation for interfaces would be easy to list, though.\r\n\r\nThen we could have a change in namespace so it becomes:\r\n\r\n    git_repo.commands.clone\r\n    git_repo.commands.fork\r\n    git_repo.commands.create\r\n    git_repo.commands.delete\r\n    git_repo.commands.open\r\n    git_repo.commands.gist\r\n    git_repo.commands.request\r\n\r\n## Use a plugin approach for services\r\n\r\nTo make it easier to implement new services, they could be offered as independent packages, that would populate in the `git_repo.services.ext` namespace, and be automagically loaded by `git-repo` when installed. Then one could only have the code for a single service at any time."},"comment":{"url":"https://api.github.com/repos/guyzmo/git-repo/issues/comments/227863124","html_url":"https://github.com/guyzmo/git-repo/issues/28#issuecomment-227863124","issue_url":"https://api.github.com/repos/guyzmo/git-repo/issues/28","id":227863124,"user":{"login":"dmerejkowsky","id":606755,"avatar_url":"https://avatars.githubusercontent.com/u/606755?v=3","gravatar_id":"","url":"https://api.github.com/users/dmerejkowsky","html_url":"https://github.com/dmerejkowsky","followers_url":"https://api.github.com/users/dmerejkowsky/followers","following_url":"https://api.github.com/users/dmerejkowsky/following{/other_user}","gists_url":"https://api.github.com/users/dmerejkowsky/gists{/gist_id}","starred_url":"https://api.github.com/users/dmerejkowsky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dmerejkowsky/subscriptions","organizations_url":"https://api.github.com/users/dmerejkowsky/orgs","repos_url":"https://api.github.com/users/dmerejkowsky/repos","events_url":"https://api.github.com/users/dmerejkowsky/events{/privacy}","received_events_url":"https://api.github.com/users/dmerejkowsky/received_events","type":"User","site_admin":false},"created_at":"2016-06-22T20:15:24Z","updated_at":"2016-06-22T20:15:24Z","body":"Interesting idea!\r\n\r\npy.test uses something similar: help and command line API change depending on the plugins installed. They use https://pypi.python.org/pypi/pluggy for this. Maybe worth trying ..."}}
{"actor":{"display_login":"dmerejkowsky"}}