def init(path, template=None, _git=None): """ Create a git repository at C{path} (if missing). Leading directories of C{path} must exist. @param path: Path of repository create. @type path: str @param template: Template directory, to pass to C{git init}. @type template: str """ if _git is None: _git = 'git' util.mkdir(path, 0750) args = [ _git, '--git-dir=.', 'init', ] if template is not None: args.append('--template=%s' % template) returncode = subprocess.call( args=args, cwd=path, stdout=sys.stderr, close_fds=True, ) if returncode != 0: raise GitInitError('exit status %d' % returncode)
def export(git_dir, path): """Export a Git repository to a given path.""" util.mkdir(path) returncode = subprocess.call( args=[ 'git', '--git-dir=%s' % git_dir, 'read-tree', 'HEAD', ], close_fds=True, ) if returncode != 0: #pragma: no cover raise GitError("read-tree", 'exit status %d' % returncode) # jumping through hoops to be compatible with git versions # that don't have --work-tree= env = {} env.update(os.environ) env['GIT_WORK_TREE'] = '.' returncode = subprocess.call( args=[ 'git', '--git-dir=%s' % os.path.abspath(git_dir), 'checkout-index', '-a', '-f', ], cwd=path, close_fds=True, env=env, ) if returncode != 0: #pragma: no cover raise GitError("checkout-index", 'exit status %d' % returncode)
def handle_args(self, parser, cfg, options, args): super(Main, self).handle_args(parser, cfg, options, args) os.umask(0022) log.info('Reading SSH public key...') pubkey = read_ssh_pubkey() user = ssh_extract_user(pubkey) if user is None: log.error('Cannot parse user from SSH public key.') sys.exit(1) log.info('Admin user is %r', user) log.info('Creating generated files directory...') generated = util.getGeneratedFilesDir(config=cfg) util.mkdir(generated) log.info('Creating repository structure...') repositories = util.getRepositoryDir(cfg) util.mkdir(repositories) #admin_repository = os.path.join(repositories, 'gitosis-admin.git') #init_admin_repository( # git_dir=admin_repository, # pubkey=pubkey, # user=user, # ) #log.info('Running post-update hook...') #util.mkdir(os.path.expanduser('~/.ssh'), 0700) #run_hook.post_update(cfg=cfg, git_dir=admin_repository) #log.info('Symlinking ~/.gitosis.conf to repository...') #symlink_config(git_dir=admin_repository) log.info('Done.')
def auto_init_repo(cfg,topdir,repopath): # create leading directories p = topdir assert repopath.endswith('.git'), 'must have .git extension' newdirmode = util.getConfigDefault(cfg, 'repo %s' % repopath[:-4], 'dirmode', None, 'defaults') if newdirmode is not None: newdirmode = int(newdirmode, 8) else: newdirmode = 0750 for segment in repopath.split(os.sep)[:-1]: p = os.path.join(p, segment) util.mkdir(p, newdirmode) fullpath = os.path.join(topdir, repopath) # init using a custom template, if required try: template = cfg.get('gitosis', 'init-template') repository.init(path=fullpath, template=template, mode=newdirmode) except (NoSectionError, NoOptionError): pass repository.init(path=fullpath, mode=newdirmode)
def init( path, template=None, _git=None, ): """ Create a git repository at C{path} (if missing). Leading directories of C{path} must exist. @param path: Path of repository create. @type path: str @param template: Template directory, to pass to C{git init}. @type template: str """ if _git is None: _git = 'git' if template is None: template = resource_filename('gitosis.templates', 'default') util.mkdir(path, 0755) args = [ _git, '--git-dir=.', 'init', ] hooks = [] if template: args.append('--template=%s' % template) template_hooks_dir = os.path.join(template, 'hooks') if os.path.isdir(template_hooks_dir): hooks = os.listdir(template_hooks_dir) returncode = subprocess.call( args=args, cwd=path, stdout=sys.stderr, close_fds=True, ) if returncode != 0: raise GitInitError('exit status %d' % returncode) hooks_dir = os.path.join(path, 'hooks') if not os.path.exists(hooks_dir): hooks_dir = os.path.join(path, '.git', 'hooks') if not os.path.exists(hooks_dir): raise for hook in hooks: mode = os.stat(os.path.join(hooks_dir, hook))[ST_MODE] if not (mode & 0755) == 0755: os.chmod( os.path.join(hooks_dir, hook), 0755)
def auto_init_repo(cfg,topdir,repopath): # create leading directories p = topdir for segment in repopath.split(os.sep)[:-1]: p = os.path.join(p, segment) util.mkdir(p, 0750) fullpath = os.path.join(topdir, repopath) # init using a custom template, if required try: template = cfg.get('gitosis', 'init-template') repository.init(path=fullpath,template=template) except (NoSectionError, NoOptionError): pass repository.init(path=fullpath)
def handle_args(self, parser, cfg, options, args): super(Main, self).handle_args(parser, cfg, options, args) os.umask(0022) log.info("Reading SSH public key...") pubkey = read_ssh_pubkey() user = ssh_extract_user(pubkey) if user is None: log.error("Cannot parse user from SSH public key.") sys.exit(1) log.info("Admin user is %r", user) log.info("Creating generated files directory...") generated = util.getGeneratedFilesDir(config=cfg) util.mkdir(generated) log.info("Creating repository structure...") repositories = util.getRepositoryDir(cfg) util.mkdir(repositories) admin_repository = os.path.join(repositories, "gitosis-admin.git") init_admin_repository(git_dir=admin_repository, pubkey=pubkey, user=user) log.info("Running post-update hook...") util.mkdir(os.path.expanduser("~/.ssh"), 0700) run_hook.post_update(cfg=cfg, git_dir=admin_repository) log.info("Symlinking ~/.gitosis.conf to repository...") symlink_config(git_dir=admin_repository) log.info("Done.")
def handle_args(self, parser, cfg, options, args): super(Main, self).handle_args(parser, cfg, options, args) os.umask(0022) log.info('Reading SSH public key...') pubkey = read_ssh_pubkey() user = ssh_extract_user(pubkey) if user is None: log.error('Cannot parse user from SSH public key.') sys.exit(1) log.info('Admin user is %r', user) log.info('Creating generated files directory...') generated = util.getGeneratedFilesDir(config=cfg) util.mkdir(generated) log.info('Creating repository structure...') repositories = util.getRepositoryDir(cfg) util.mkdir(repositories) admin_repository = os.path.join(repositories, 'gitosis-admin') # CQDE change: removed .git extension. init_admin_repository( git_dir=admin_repository, pubkey=pubkey, user=user, ) log.info('Running post-update hook...') util.mkdir(os.path.expanduser('~/.ssh'), 0700) run_hook.post_update(cfg=cfg, git_dir=admin_repository) log.info('Symlinking ~/.gitosis.conf to repository...') symlink_config(git_dir=admin_repository) log.info('Done.')
def init( path, template=None, _git=None, ): """ Create a git repository at C{path} (if missing). Leading directories of C{path} must exist. @param path: Path of repository create. @type path: str @param template: Template directory, to pass to C{git init}. @type template: str """ if _git is None: _git = 'git' util.mkdir(path, 0o750) args = [ _git, '--git-dir=.', 'init', '--quiet', ] if template is not None: args.append('--template=%s' % template) returncode = subprocess.call( args=args, cwd=path, stdout=sys.stderr, close_fds=True, ) if returncode != 0: raise GitInitError('exit status %d' % returncode)
def handle_args(self, parser, cfg, options, args): #pragma: no cover """Parse the input for this program.""" super(Main, self).handle_args(parser, cfg, options, args) os.umask(0022) log.info('Reading SSH public key...') pubkey = read_ssh_pubkey(options.adminkey) if options.adminname is None: _ = sshkey.get_ssh_pubkey(pubkey) user = _.username else: user = options.adminname user = user.strip() if user is None: log.error('Cannot parse user from SSH public key.') sys.exit(1) log.info('Admin user is %r', user) log.info('Creating generated files directory...') generated = cfg.generated_files_dir util.mkdir(generated) log.info('Creating repository structure...') repositories = cfg.repository_dir util.mkdir(repositories) admin_repository = os.path.join(repositories, 'gitosis-admin.git') init_admin_repository( git_dir=admin_repository, pubkey=pubkey, user=user, config=cfg, ) log.info('Running post-update hook...') util.mkdir(os.path.expanduser('~/.ssh'), 0700) run_hook.post_update(cfg=cfg, git_dir=admin_repository) log.info('Symlinking ~/.gitosis.conf to repository...') symlink_config(git_dir=admin_repository) log.info('Done.')
def serve( cfg, user, command, ): if '\n' in command: raise CommandMayNotContainNewlineError() try: verb, args = command.split(None, 1) except ValueError: # all known "git-foo" commands take one argument; improve # if/when needed raise UnknownCommandError() if verb == 'git': try: subverb, args = args.split(None, 1) except ValueError: # all known "git foo" commands take one argument; improve # if/when needed raise UnknownCommandError() verb = '%s %s' % (verb, subverb) if (verb not in COMMANDS_WRITE and verb not in COMMANDS_READONLY): raise UnknownCommandError() match = ALLOW_RE.match(args) if match is None: raise UnsafeArgumentsError() path = match.group('path') # write access is always sufficient newpath = access.haveAccess( config=cfg, user=user, mode='writable', path=path) if newpath is None: # didn't have write access; try once more with the popular # misspelling newpath = access.haveAccess( config=cfg, user=user, mode='writeable', path=path) if newpath is not None: log.warning( 'Repository %r config has typo "writeable", ' +'should be "writable"', path, ) if newpath is None: # didn't have write access newpath = access.haveAccess( config=cfg, user=user, mode='readonly', path=path) if newpath is None: raise ReadAccessDenied() if verb in COMMANDS_WRITE: # didn't have write access and tried to write raise WriteAccessDenied() (topdir, relpath) = newpath assert not relpath.endswith('.git'), \ 'git extension should have been stripped: %r' % relpath repopath = '%s.git' % relpath fullpath = os.path.join(topdir, repopath) if (not os.path.exists(fullpath) and verb in COMMANDS_WRITE): # it doesn't exist on the filesystem, but the configuration # refers to it, we're serving a write request, and the user is # authorized to do that: create the repository on the fly # create leading directories p = topdir for segment in repopath.split(os.sep)[:-1]: p = os.path.join(p, segment) util.mkdir(p, 0755) repository.init(path=fullpath) gitweb.set_descriptions( config=cfg, ) generated = util.getGeneratedFilesDir(config=cfg) gitweb.generate_project_list( config=cfg, path=os.path.join(generated, 'projects.list'), ) gitdaemon.set_export_ok( config=cfg, ) # put the verb back together with the new path newcmd = "%(verb)s '%(path)s'" % dict( verb=verb, path=fullpath, ) return newcmd
def serve( cfg, user, command, ): if '\n' in command: raise CommandMayNotContainNewlineError() try: verb, args = command.split(None, 1) except ValueError: # all known "git-foo" commands take one argument; improve # if/when needed raise UnknownCommandError() if verb == 'git': try: subverb, args = args.split(None, 1) except ValueError: # all known "git foo" commands take one argument; improve # if/when needed raise UnknownCommandError() verb = '%s %s' % (verb, subverb) if (verb not in COMMANDS_WRITE and verb not in COMMANDS_READONLY): raise UnknownCommandError() try: match = ALLOW_RE.match(unicode(args, 'utf-8')) except UnicodeDecodeError: raise UnsafeArgumentsError() if match is None: raise UnsafeArgumentsError() path = match.group('path') # admin access is always sufficient newpath = access.haveAccess( config=cfg, user=user, mode='admin', path=path) # write access is always sufficient if newpath is None: newpath = access.haveAccess( config=cfg, user=user, mode='write', path=path) if newpath is None: # didn't have write access newpath = access.haveAccess( config=cfg, user=user, mode='read', path=path) if newpath is None: raise ReadAccessDenied() if verb in COMMANDS_WRITE: # didn't have write access and tried to write raise WriteAccessDenied() (topdir, relpath, mode) = newpath assert not relpath.endswith('.git'), \ 'git extension should have been stripped: %r' % relpath repopath = '%s.git' % relpath fullpath = os.path.join(topdir, repopath) if not os.path.exists(fullpath) and verb in COMMANDS_WRITE: # it doesn't exist on the filesystem, but the configuration # refers to it, we're serving a write request, and the user is # authorized to do that: create the repository on the fly # If user not has admin permission, raise a Error if mode != 'admin': raise InitAccessDenied() # create leading directories p = topdir for segment in repopath.split(os.sep)[:-1]: p = os.path.join(p, segment) util.mkdir(p, 0755) repository.init(path=fullpath) # only update description of this repository gitweb.set_repo_descriptions( config=cfg, path=fullpath, ) # not update projects.list here, but in gitosis-admin post-update # only update export flag of this repository gitdaemon.set_repo_export_ok( config=cfg, path=fullpath, ) # put the verb back together with the new path newcmd = "%(verb)s '%(path)s'" % dict( verb=verb, path=fullpath, ) return newcmd
@param template: Template directory, to pass to C{git init}. @type template: str @param mode: Permissions for the new reposistory @type mode: int """ if _git is None: _git = 'git' if template is None: template = resource_filename('gitosis.templates', 'default') util.mkdir(path, mode) args = [ _git, '--git-dir=.', 'init', ] hooks = [] if template: args.append('--template=%s' % template) template_hooks_dir = os.path.join(template, 'hooks') if os.path.isdir(template_hooks_dir): hooks = os.listdir(template_hooks_dir) returncode = subprocess.call( args=args,
def serve( cfg, user, command, ): if '\n' in command: raise CommandMayNotContainNewlineError() try: verb, args = command.split(None, 1) except ValueError: # all known "git-foo" commands take one argument; improve # if/when needed raise UnknownCommandError() if verb == 'git': try: subverb, args = args.split(None, 1) except ValueError: # all known "git foo" commands take one argument; improve # if/when needed raise UnknownCommandError() verb = '%s %s' % (verb, subverb) if (verb not in COMMANDS_WRITE and verb not in COMMANDS_READONLY): raise UnknownCommandError() match = ALLOW_RE.match(args) if match is None: raise UnsafeArgumentsError() path = match.group('path') # write access is always sufficient newpath = access.haveAccess( config=cfg, user=user, mode='writable', path=path) if newpath is None: # didn't have write access; try once more with the popular # misspelling newpath = access.haveAccess( config=cfg, user=user, mode='writeable', path=path) if newpath is not None: log.warning( 'Repository %r config has typo "writeable", ' +'should be "writable"', path, ) if newpath is None: # didn't have write access newpath = access.haveAccess( config=cfg, user=user, mode='readonly', path=path) if newpath is None: raise ReadAccessDenied() if verb in COMMANDS_WRITE: # didn't have write access and tried to write raise WriteAccessDenied() (topdir, relpath) = newpath assert not relpath.endswith('.git'), \ 'git extension should have been stripped: %r' % relpath repopath = '%s.git' % relpath fullpath = os.path.join(topdir, repopath) if not os.path.exists(fullpath): # it doesn't exist on the filesystem, but the configuration # refers to it, we're serving a write request, and the user is # authorized to do that: create the repository on the fly # create leading directories p = topdir for segment in repopath.split(os.sep)[:-1]: p = os.path.join(p, segment) util.mkdir(p, 0o750) repository.init(path=fullpath) gitweb.set_descriptions( config=cfg, ) generated = util.getGeneratedFilesDir(config=cfg) gitweb.generate_project_list( config=cfg, path=os.path.join(generated, 'projects.list'), ) gitdaemon.set_export_ok( config=cfg, ) # put the verb back together with the new path newcmd = "%(verb)s '%(path)s'" % dict( verb=verb, path=fullpath, ) return newcmd
def serve(cfg, user, command): """Check the git command for sanity, and then run the git command.""" log = logging.getLogger('gitosis.serve.serve') if '\n' in command: raise CommandMayNotContainNewlineError() try: verb, args = command.split(None, 1) except ValueError: # all known "git-foo" commands take one argument; improve # if/when needed raise UnknownCommandError() if verb == 'git': try: subverb, args = args.split(None, 1) except ValueError: # all known "git foo" commands take one argument; improve # if/when needed raise UnknownCommandError() verb = '%s %s' % (verb, subverb) if (verb not in COMMANDS_WRITE and verb not in COMMANDS_READONLY): raise UnknownCommandError() log.debug('Got command %(cmd)r and args %(args)r' % dict( cmd=verb, args=args, )) if args.startswith("'/") and args.endswith("'"): args = args[1:-1] repos = cfg.repository_dir reposreal = os.path.realpath(repos) if args.startswith(repos): args = os.path.realpath(args)[len(repos)+1:] elif args.startswith(reposreal): args = os.path.realpath(args)[len(reposreal)+1:] else: args = args[1:] args = "'%s'" % (args, ) match = ALLOW_RE.match(args) if match is None: raise UnsafeArgumentsError() path = match.group('path') # write access is always sufficient newpath = access.allowed( config=cfg, user=user, mode='writable', path=path) if newpath is None: # didn't have write access; try once more with the popular # misspelling newpath = access.allowed( config=cfg, user=user, mode='writeable', path=path) if newpath is not None: log.warning('Repository %r config has typo "writeable", ' +'should be "writable"', path, ) if newpath is None: # didn't have write access newpath = access.allowed( config=cfg, user=user, mode='readonly', path=path) if newpath is None: raise ReadAccessDenied() if verb in COMMANDS_WRITE: # didn't have write access and tried to write raise WriteAccessDenied() (topdir, relpath) = newpath assert not relpath.endswith('.git'), \ 'git extension should have been stripped: %r' % relpath repopath = '%s.git' % relpath fullpath = os.path.join(topdir, repopath) if not os.path.exists(fullpath): # it doesn't exist on the filesystem, but the configuration # refers to it, we're serving a write request, and the user is # authorized to do that: create the repository on the fly # create leading directories path = topdir newdirmode = cfg.get('repo %s' % (relpath, ), 'dirmode') if newdirmode is None: newdirmode = cfg.get('gitosis', 'dirmode', default='0750') # Convert string as octal to a number newdirmode = int(newdirmode, 8) for segment in repopath.split(os.sep)[:-1]: path = os.path.join(path, segment) util.mkdir(path, newdirmode) repository.init(path=fullpath, mode=newdirmode) run_hook.build_reposistory_data(cfg) # put the verb back together with the new path newcmd = "%(verb)s '%(path)s'" % dict( verb=verb, path=fullpath, ) return newcmd
def serve(cfg, user, command): if "\n" in command: raise CommandMayNotContainNewlineError() try: verb, args = command.split(None, 1) except ValueError: # all known "git-foo" commands take one argument; improve # if/when needed raise UnknownCommandError() if verb == "git": try: subverb, args = args.split(None, 1) except ValueError: # all known "git foo" commands take one argument; improve # if/when needed raise UnknownCommandError() verb = "%s %s" % (verb, subverb) if verb not in COMMANDS_WRITE and verb not in COMMANDS_READONLY: raise UnknownCommandError() match = ALLOW_RE.match(args) if match is None: raise UnsafeArgumentsError() path = match.group("path") decode_id = cfg.get_gitosis("decodeID") if decode_id and util.parse_bool(decode_id): encoded_user = user user = util.decode_id(encoded_user) log.debug("decodeID = yes, decode '%s' as '%s'" % (encoded_user, user)) if not user: raise BadEncodedID() newpath = access.haveAccess(config=cfg, user=user, mode="RW+", path=path) if newpath == None: if verb in COMMANDS_WRITE: raise WriteAccessDenied() else: newpath = access.haveAccess(config=cfg, user=user, mode="R", path=path) if newpath == None: raise ReadAccessDenied() (repobase, reponame) = newpath assert not reponame.endswith(".git"), "git extension should have been stripped: %r" % reponame repopath = reponame + ".git" fullpath = os.path.join(repobase, repopath) if not os.path.exists(fullpath): # it doesn't exist on the filesystem, but the configuration # refers to it, we're serving a write request, and the user is # authorized to do that: create the repository on the fly # create leading directories p = repobase components = repopath.split(os.sep)[:-1] for c in components: # Check if c.endswith(".git"): raise BadRepositoryPath() for c in components: p = os.path.join(p, c) util.mkdir(p, 0750) props = (gitdaemon.DaemonProp(), gitweb.GitwebProp(), gitweb.DescriptionProp(), gitweb.OwnerProp()) ext_props = cfg.get_gitosis("extProps") or () if ext_props: try: ext_props_expanded = os.path.join(os.path.expanduser("~"), ext_props) dir_ = os.path.dirname(ext_props_expanded) file_ = os.path.basename(ext_props_expanded) mod_, ext_ = os.path.splitext(file_) assert mod_, "'%s': empty module name" % file_ assert ext_ == ".py", "the extname of '%s' is not '.py'" % file_ sys.path.append(dir_) mod_ = __import__(mod_) ext_props_ = mod_.get_props() except (AssertionError, ImportError) as e: log.warning("Invalid extProps value '%s': %s" % (ext_props, str(e))) ext_props = () except: log.warning("Bad module '%s': %s" % (ext_props, str(sys.exc_info()[1]))) ext_props = () else: ext_props = ext_props_ repository.init(path=fullpath) util.RepositoryDir(cfg, props + ext_props).visit_one(reponame) generated = util.getGeneratedFilesDir(config=cfg) gitweb.ProjectList(os.path.join(generated, "projects.list")).update() # put the verb back together with the new path newcmd = "%(verb)s '%(path)s'" % dict(verb=verb, path=fullpath) return newcmd