def test_overwrite_filelocking(): path = 'tests/fixtures/empty_repo.conf' mocked_path = MagicMock() mocked_path.__str__ = lambda x: path mocked_fcntl = MagicMock() mocked_open = MagicMock() with patch('pyolite.repo.open', mocked_open, create=True): manager = mocked_open.return_value.__enter__.return_value # asserts file locking has been put in place before writing manager.write = lambda text: ([ mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl. LOCK_EX), mocked_fcntl.reset_mock() ]) with patch.multiple('pyolite.repo', fcntl=mocked_fcntl): repo = Repo(path) mocked_fcntl.reset_mock() repo.overwrite('some_text') # asserts lock has been removed after writing mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl.LOCK_UN)
def test_overwrite_filelocking(): path = 'tests/fixtures/empty_repo.conf' mocked_path = MagicMock() mocked_path.__str__ = lambda x: path mocked_fcntl = MagicMock() mocked_open = MagicMock() with patch('pyolite.repo.open', mocked_open, create=True): manager = mocked_open.return_value.__enter__.return_value # asserts file locking has been put in place before writing manager.write = lambda text: ([ mocked_fcntl.flock.assert_called_once_with( manager, mocked_fcntl.LOCK_EX ), mocked_fcntl.reset_mock() ]) with patch.multiple('pyolite.repo', fcntl=mocked_fcntl): repo = Repo(path) mocked_fcntl.reset_mock() repo.overwrite('some_text') # asserts lock has been removed after writing mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl.LOCK_UN)
def test_replace_filelocking(): mocked_re = MagicMock() mocked_fcntl = MagicMock() mocked_open = MagicMock() path = 'tests/fixtures/config.conf' with patch('pyolite.repo.open', mocked_open, create=True): manager = mocked_open.return_value.__enter__.return_value # asserts file locking has been put in place before reading manager.read = lambda: ([ mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl. LOCK_EX), mocked_fcntl.reset_mock() ]) with patch.multiple('pyolite.repo', re=mocked_re, fcntl=mocked_fcntl): repo = Repo(path) mocked_fcntl.reset_mock() repo.replace('pattern', 'string') # asserts lock has been removed after operating on file mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl.LOCK_UN)
def test_replace_filelocking(): mocked_re = MagicMock() mocked_fcntl = MagicMock() mocked_open = MagicMock() path = 'tests/fixtures/config.conf' with patch('pyolite.repo.open', mocked_open, create=True): manager = mocked_open.return_value.__enter__.return_value # asserts file locking has been put in place before reading manager.read = lambda: ([ mocked_fcntl.flock.assert_called_once_with( manager, mocked_fcntl.LOCK_EX ), mocked_fcntl.reset_mock() ]) with patch.multiple('pyolite.repo', re=mocked_re, fcntl=mocked_fcntl): repo = Repo(path) mocked_fcntl.reset_mock() repo.replace('pattern', 'string') # asserts lock has been removed after operating on file mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl.LOCK_UN)
def __init__(self, name, path, git): self.name = name self.path = path self.git = git self.repo = Repo(Path(path, "conf/repos/%s.conf" % name)) self.users = ListUsers(self)
def test_it_should_overwrite_the_repo_config(): path = 'tests/fixtures/empty_repo.conf' Repo(path).write('some_text') Repo(path).overwrite('another_text') with open(path, 'r+') as f: assert f.read() == 'another_text' f.seek(0) f.write('') f.truncate()
def test_it_should_replace_a_given_string_in_repo_conf(): mocked_re = MagicMock() path = 'tests/fixtures/config.conf' mocked_re.sub.return_value = 'another_text' with patch.multiple('pyolite.repo', re=mocked_re): repo = Repo(path) repo.replace('pattern', 'string') with open('tests/fixtures/config.conf') as f: assert f.read() == 'another_text' mocked_re.sub.assert_called_once_with('pattern', 'string', 'another_text')
def test_users_filelocking(): path = 'tests/fixtures/repo_users.conf' mocked_path = MagicMock() mocked_path.__str__ = lambda x: path mocked_path.exists.return_value = True mocked_re = MagicMock() mocked_fcntl = MagicMock() mocked_open = MagicMock() with patch('pyolite.repo.open', mocked_open, create=True): manager = mocked_open.return_value.__enter__.return_value # asserts file locking has been put in place before reading manager.read = lambda: ([ mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl. LOCK_EX), mocked_fcntl.reset_mock() ]) with patch.multiple('pyolite.repo', re=mocked_re, fcntl=mocked_fcntl): repo = Repo(mocked_path) mocked_fcntl.reset_mock() repo.users # asserts lock has been removed after reading mocked_fcntl.flock.assert_called_once_with(manager, mocked_fcntl.LOCK_UN)
def test_it_should_write_to_repo_config(self): path = 'tests/fixtures/empty_repo.conf' Repo(path).write('some_text') with open(path, 'r+') as f: eq_('some_text', f.read()) f.seek(0) f.write('') f.truncate()
def test_setting_config_will_not_overwrite_users(): path = 'tests/fixtures/empty_repo.conf' Repo(path).write(''' repo test-repo RW+ = @support R = gitweb config test = testconfig ''') Repo(path).write_config(" config another = anotherconfig\n") with open(path, 'r+') as f: assert f.read() == ''' repo test-repo RW+ = @support R = gitweb config another = anotherconfig ''' f.seek(0) f.write('') f.truncate()
def test_it_should_retrieve_all_users_from_repo(): path = 'tests/fixtures/repo_users.conf' mocked_path = MagicMock() mocked_path.__str__ = lambda x: path mocked_path.exists.return_value = True mocked_re = MagicMock() mocked_user1 = MagicMock() mocked_user2 = MagicMock() mocked_re.compile('=( *)(\w+)').finditer.return_value = [ mocked_user1, mocked_user2 ] mocked_user1.group.return_value = 'user1' mocked_user2.group.return_value = 'user2' with patch.multiple('pyolite.repo', re=mocked_re): repo = Repo(mocked_path) assert repo.users == ['user1', 'user2']
class ListUsers(object): def __init__(self, repository): self.repository_model = repository self.repo = Repo(Path(repository.path, "conf/repos/%s.conf" % repository.name)) def with_user(func): def decorated(self, string_user, *args, **kwargs): try: user = User.get(string_user, self.repository_model.path, self.repository_model.git) except ValueError: user = User(self.repository_model.path, self.repository_model.git, string_user) return func(self, user, *args, **kwargs) return decorated @with_user def add(self, user, permission): if user.name in self.repo.users: raise ValueError('User %s already exists. Please check ' 'example/repository.py in order to see how you can ' 'delete or change permissions' % user.name) if set(map(lambda permission: permission.upper(), permission)) - \ ACCEPTED_PERMISSIONS != set([]): raise ValueError('Invalid permissions. They must be from %s' % ACCEPTED_PERMISSIONS) self.repo.write(" %s = %s\n" % (permission, user.name)) commit_message = 'User %s added to repo %s with permissions: %s' %\ (user, self.repository_model.name, permission) self.repository_model.git.commit(['conf'], commit_message) user.repos.append(self.repo) return user @with_user def edit(self, user, permission): pattern = r'(\s*)([RW+DC]*)(\s*)=(\s*)%s' % user.name string = r"\n %s = %s" % (permission, user.name) self.repo.replace(pattern, string) self.repository_model.git.commit(['conf'], "User %s has %s permission for repository %s" % (user.name, permission, self.repository_model.name)) return user @with_user def remove(self, user): pattern = r'(\s*)([RW+DC]*)(\s*)=(\s*)%s' % user.name self.repo.replace(pattern, "") self.repository_model.git.commit(['conf'], "Deleted user %s from repository %s" % (user.name, self.repository_model.name)) def __iter__(self): for user in self._user: yield user def __getitem__(self, item): return self._users[item] def __setitem__(self, item, value): self._users[item] = value def __add__(self, items): for item in items: self.append(item) def __str__(self): return "['%s']" % ', '.join(self.repo.users)
def __init__(self, repository): self.repository_model = repository self.repo = Repo(Path(repository.path, "conf/repos/%s.conf" % repository.name))
class ListUsers(object): def __init__(self, repository): self.repository_model = repository self.repo = Repo(Path(repository.path, "conf/repos/%s.conf" % repository.name)) @with_user def add(self, user, permission): if user.name in self.repo.users: raise ValueError('User %s already exists. Please check ' 'example/repository.py in order to see how you can ' 'delete or change permissions' % user.name) if set(map(lambda permission: permission.upper(), permission)) - \ ACCEPTED_PERMISSIONS != set([]): raise ValueError('Invalid permissions. They must be from %s' % ACCEPTED_PERMISSIONS) self.repo.write(" %s = %s\n" % (permission, user.name)) commit_message = 'User %s added to repo %s with permissions: %s' % \ (user, self.repository_model.name, permission) self.repository_model.git.commit(['conf'], commit_message) user.repos.append(self.repo) return user @with_user def edit(self, user, permission): pattern = USER_PATTERN % user.name string = r"\n %s = %s" % (permission, user.name) self.repo.replace(pattern, string) self.repository_model.git.commit(['conf'], "User %s has %s permission for repository %s" % (user.name, permission, self.repository_model.name)) return user @with_user def remove(self, user): pattern = USER_PATTERN % user.name self.repo.replace(pattern, "") self.repository_model.git.commit(['conf'], "Deleted user %s from repository %s" % (user.name, self.repository_model.name)) @with_user def get_or_create(self, user): return user def set(self, users=None, overwrite_config=False): users_serialized = "repo {}\n".format(self.repository_model.name) if isinstance(users, dict): users = users.iteritems() if users: for user, permission in users: if not hasattr(user, 'name'): user = self.get_or_create(user) users_serialized += " %s = %s\n" % (permission, user.name) config = "" if overwrite_config else self.repository_model.get_config() self.repo.overwrite(users_serialized + config) users = ", ".join((user for user, permission in users)) commit_message = "Initialized repository %s with users: %s" % ( self.repository_model.name, users ) self.repository_model.git.commit(['conf'], commit_message) def __iter__(self): for user in self._users: yield user def __getitem__(self, item): return self._users[item] def __setitem__(self, item, value): self._users[item] = value def __add__(self, items): for item in items: self.append(item) def __str__(self): return "['%s']" % ', '.join(self.repo.users)
class ListUsers(object): def __init__(self, repository): self.repository_model = repository self.repo = Repo(Path(repository.path, "conf/repos/%s.conf" % repository.name)) def with_user(func): def decorated(self, string_user, *args, **kwargs): try: user = User.get(string_user, self.repository_model.path, self.repository_model.git) except ValueError: user = User(self.repository_model.path, self.repository_model.git, string_user) return func(self, user, *args, **kwargs) return decorated @with_user def add(self, user, permission): if user.name in self.repo.users: raise ValueError('User %s already exists. Please check ' 'example/repository.py in order to see how you can ' 'delete or change permissions' % user.name) if set(map(lambda permission: permission.upper(), permission)) - \ ACCEPTED_PERMISSIONS != set([]): raise ValueError('Invalid permissions. They must be from %s' % ACCEPTED_PERMISSIONS) self.repo.write(" %s = %s\n" % (permission, user.name)) commit_message = 'User %s added to repo %s with permissions: %s' % \ (user, self.repository_model.name, permission) self.repository_model.git.commit(['conf'], commit_message) user.repos.append(self.repo) return user @with_user def edit(self, user, permission): if user.name not in self.repo.users: raise ValueError('User %s not exists in repo %s' % (user.name, self.repository_model.name)) if set(map(lambda permission: permission.upper(), permission)) - \ ACCEPTED_PERMISSIONS != set([]): raise ValueError('Invalid permissions. They must be from %s' % ACCEPTED_PERMISSIONS) pattern = r'(\s*)([RW+DC]*)(\s*)=(\s*)%s' % user.name string = r"\n %s = %s" % (permission, user.name) self.repo.replace(pattern, string) self.repository_model.git.commit(['conf'], "User %s has %s permission for repository %s" % (user.name, permission, self.repository_model.name)) return user @with_user def remove(self, user): pattern = r'(\s*)([RW+DC]*)(\s*)=(\s*)%s' % user.name self.repo.replace(pattern, "") self.repository_model.git.commit(['conf'], "Deleted user %s from repository %s" % (user.name, self.repository_model.name)) @with_user def get_or_create(self, user): return user def set(self, users=None): users_serialized = "repo {}\n".format(self.repository_model.name) if isinstance(users, dict): users = users.iteritems() if users: for user, permission in users: if not hasattr(user, 'name'): user = self.get_or_create(user) users_serialized += " %s = %s\n" % (permission, user.name) self.repo.overwrite(users_serialized) users = ", ".join((user for user, permission in users)) commit_message = "Initialized repository %s with users: %s" % ( self.repository_model.name, users ) self.repository_model.git.commit(['conf'], commit_message) # def __iter__(self): # for user in self._user: # yield user # def __getitem__(self, item): # return self._users[item] # def __setitem__(self, item, value): # self._users[item] = value # def __add__(self, items): # for item in items: # self.append(item) def __str__(self): return "['%s']" % ', '.join(self.repo.users)
class Repository(object): def __init__(self, name, path, git): self.name = name self.path = path self.git = git self.repo = Repo(Path(path, "conf/repos/%s.conf" % name)) self.users = ListUsers(self) @classmethod def get_by_name(cls, lookup_repo, path, git): for obj in Path(path, 'conf').walk(): if obj.isdir(): continue with open(str(obj)) as f: try: first_line = f.read().split('\n')[0] except IndexError: return None if "repo %s" % lookup_repo == first_line.strip(): return cls(lookup_repo, path, git) return None def get_config(self): return self._serialize_config() def add_config(self, values): if isinstance(values, dict): raw_values = values.items() elif isinstance(values, list) or isinstance(values, set) or isinstance(values, tuple): if len(values) > 2: raise ValueError("Use a dict if you want to set multiple values.") raw_values = [values] else: raise ValueError("Accepted config types are: dict, tuple, list and set.") current_config = self._read_current_config() for config in raw_values: current_config[config[0]] = config[1] self.repo.write_config(self._serialize_config(current_config)) self.git.commit(['conf'], "Update %s's config" % self.name) def _serialize_config(self, structured_config=None): structured_config = structured_config or self._read_current_config() config = "" for name, value in structured_config.items(): config += " config %s = %s\n" % (name, value) return config def _read_current_config(self): return OrderedDict(**{ result.group(3): result.group(6) for result in re.finditer(CONFIG_PATTERN, self.repo.read()) }) def __str__(self): return "< %s >" % self.name
class Repository(object): def __init__(self, name, path, git): self.name = name self.path = path self.git = git self.repo = Repo(Path(path, "conf/repos/%s.conf" % name)) self.users = ListUsers(self) @classmethod def get_by_name(cls, lookup_repo, path, git): for obj in Path(path, 'conf').walk(): if obj.isdir(): continue with open(str(obj)) as f: try: first_line = f.read().split('\n')[0] except IndexError: return None if "repo %s" % lookup_repo == first_line.strip(): return cls(lookup_repo, path, git) return None def get_config(self): return self._serialize_config() def add_config(self, values): if isinstance(values, dict): raw_values = values.items() elif isinstance(values, list) or isinstance(values, set) or isinstance( values, tuple): if len(values) > 2: raise ValueError( "Use a dict if you want to set multiple values.") raw_values = [values] else: raise ValueError( "Accepted config types are: dict, tuple, list and set.") current_config = self._read_current_config() for config in raw_values: current_config[config[0]] = config[1] self.repo.write_config(self._serialize_config(current_config)) self.git.commit(['conf'], "Update %s's config" % self.name) def _serialize_config(self, structured_config=None): structured_config = structured_config or self._read_current_config() config = "" for name, value in structured_config.items(): config += " config %s = %s\n" % (name, value) return config def _read_current_config(self): return OrderedDict( **{ result.group(3): result.group(6) for result in re.finditer(CONFIG_PATTERN, self.repo.read()) }) def __str__(self): return "< %s >" % self.name