class TestTree(unittest.TestCase): def setUp(self): os.chdir('/tmp') self.repo_name = 'hellogit-testrepo' self.init = Init() self.init.create_git_repo(self.repo_name) self.add = Add() filename = 'hello' content = 'hello world\n' pwd = os.getcwd() os.chdir(os.path.join(pwd, self.repo_name)) with open(filename, 'w') as f: f.write(content) content_hash = self.add.create_blob(filename) self.tree = Tree() def tearDown(self): os.chdir('/tmp') shutil.rmtree(self.repo_name, ignore_errors=True) def test_create_tree_successfully(self): tree_entry = self.tree.create_tree() expected_tree_entry = TreeEntry( self.repo_name, entry_type=EntryType.TREE, sha1='6a98fd9cb9c98a860866e8a309f51c0686baa3e8') self.assertEqual(str(tree_entry), str(expected_tree_entry), 'Incorrect tree hash')
class TestInit(unittest.TestCase): def setUp(self): self.repo_name = 'hellogit-testrepo' self.init = Init() def tearDown(self): shutil.rmtree(self.repo_name, ignore_errors=True) def test_create_git_repo(self): self.init.create_git_repo(self.repo_name) pwd = os.getcwd() repo_path = os.path.join(pwd, self.repo_name, '.git') repo_dir = os.path.exists(repo_path) objects_path = os.path.join(pwd, self.repo_name, '.git', 'objects') objects_dir = os.path.exists(objects_path) refs_path = os.path.join(pwd, self.repo_name, '.git', 'refs', 'heads') refs_dir = os.path.exists(refs_path) HEAD_path = os.path.join(pwd, self.repo_name, '.git', 'HEAD') HEAD_file = os.path.exists(HEAD_path) self.assertTrue(repo_dir, 'Failed to create the .git directory') self.assertTrue(objects_dir, 'Failed to create the .git/objects directory') self.assertTrue(refs_dir, 'Failed to create the .git/refs/heads directory') self.assertTrue(HEAD_file, 'Failed to create the .git/HEAD reference file') def test_create_git_repo_with_special_character_should_fail(self): repo_name = 'hellogit*' with self.assertRaises( FileNamingConventionError, msg= 'Using special characters in repo name should not be allowed. Only allowing [a-zA-Z0-9_.-] for repo name' ): git_init = Init() git_init.create_git_repo(repo_name) def test_create_git_bare_repo(self): self.init.create_git_repo(self.repo_name, bare_repo=True) pwd = os.getcwd() objects_path = os.path.join(pwd, self.repo_name, 'objects') objects_dir = os.path.exists(objects_path) refs_path = os.path.join(pwd, self.repo_name, 'refs', 'heads') refs_dir = os.path.exists(refs_path) HEAD_path = os.path.join(pwd, self.repo_name, 'HEAD') HEAD_file = os.path.exists(HEAD_path) self.assertTrue(objects_dir, 'Failed to create the objects directory') self.assertTrue(refs_dir, 'Failed to create the refs/heads directory') self.assertTrue(HEAD_file, 'Failed to create the HEAD reference file')
def test_create_git_repo_with_special_character_should_fail(self): repo_name = 'hellogit*' with self.assertRaises( FileNamingConventionError, msg= 'Using special characters in repo name should not be allowed. Only allowing [a-zA-Z0-9_.-] for repo name' ): git_init = Init() git_init.create_git_repo(repo_name)
def main(): logger.info('Calling git main()') parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='subparser_name') init_parser = subparsers.add_parser('init', help='Create an empty Git repository') init_parser.add_argument( 'repo_name', help= 'New repository name. Should only use letters, digits, _, ., and - in the name' ) init_parser.add_argument('--bare', action='store_true', help='Create a bare repository') add_parser = subparsers.add_parser( 'add', help='Add new/changed file to the repository') add_parser.add_argument('pathname', help='The files or directoies to be added') commit_parser = subparsers.add_parser( 'commit', help='Commit staging changes to the repository') commit_parser.add_argument('--author', default='NO AUTHOR', help='Specify an explicit author name') commit_parser.add_argument( '-m', '--message', required=True, help='Use the given message as the commit message') args = parser.parse_args() if 'init' == args.subparser_name: logger.info('Called with init repo_name {}'.format(args.repo_name)) init = Init() init.create_git_repo(args.repo_name, args.bare) elif 'add' == args.subparser_name: logger.info('Called with add pathname {}'.format(args.pathname)) add = Add() add.create_blob(args.pathname) elif 'commit' == args.subparser_name: logger.info('Called with commit') tree = Tree() root_tree_entry = tree.create_tree() commit = Commit() commit.create_commit(author=args.author, commit_message=args.message, root_tree_entry=root_tree_entry) else: parser.print_help()
class TestRepo(unittest.TestCase): def setUp(self): os.chdir('/tmp') self.repo_name = 'hello-git' self.init = Init() self.init.create_git_repo(self.repo_name) os.chdir('/tmp/hello-git') self.git_repo = Repo() def tearDown(self): os.chdir('/tmp') full_path = os.path.join('/tmp', self.repo_name) shutil.rmtree(full_path, ignore_errors=True) def test_good_repo_name_should_return_true(self): good_name = self.git_repo.verify_naming_convention(self.repo_name) self.assertTrue(good_name, 'The repo name is valid with [a-zA-Z0-9_.-] but failed to validate') def test_bad_repo_name_should_raise_exception(self): with self.assertRaises(FileNamingConventionError, msg='The repo name is invalid with special character. Only [a-zA-Z0-9_.-] are allowed'): repo_name = 'hello-git*' self.git_repo.verify_naming_convention(repo_name) def test_duplicate_repo_name_should_raise_exception(self): real_os_path_exists = os.path.exists os.path.exists = MagicMock(return_value=True) with self.assertRaises(FileExistsError, msg='The git repository hello-git already exists!'): self.git_repo.repo_exist(self.repo_name) os.path.exists = real_os_path_exists def test_get_repo_root_when_git_at_the_current_directory_level(self): full_path = os.path.join('/tmp', self.repo_name) os.chdir(full_path) repo_root_dir = self.git_repo.get_repo_root(full_path) expected_path = os.path.join(full_path, '.git') self.assertEqual(expected_path, repo_root_dir) def test_get_repo_root_on_a_non_git_repo_should_raise_exception(self): non_git_dir = '/tmp/non-repo' os.makedirs(non_git_dir) os.chdir(non_git_dir) with self.assertRaises(NotGitRepoError, msg='Not a git repository. Please run `git init` at the top-most level of this project'): self.git_repo.get_repo_root(non_git_dir) os.chdir('/tmp') shutil.rmtree(non_git_dir, ignore_errors=True)
class TestCommit(unittest.TestCase): def setUp(self): os.chdir('/tmp') self.repo_name = 'hellogit-testrepo' self.init = Init() self.init.create_git_repo(self.repo_name) add = Add() filename = 'hello' content = 'hello world\n' pwd = os.getcwd() os.chdir(os.path.join(pwd, self.repo_name)) with open(filename, 'w') as f: f.write(content) content_hash = add.create_blob(filename) tree = Tree() self.tree_entry = tree.create_tree() self.commit = Commit() def tearDown(self): os.chdir('/tmp') shutil.rmtree(self.repo_name, ignore_errors=True) def test_create_commit_successfully(self): author = 'name author' mock_timestamp = 1532961836 message = 'test commit message for hello world' parents = ['0' * 40] original_time = time.time time.time = MagicMock(return_value=mock_timestamp) commit_hash = self.commit.create_commit(author=author, commit_message=message, root_tree_entry=self.tree_entry) time.time = original_time expected_commit_entry = 'tree: 6a98fd9cb9c98a860866e8a309f51c0686baa3e8\nparents: {}\nauthor: {} <NO EMAIL> {} +0000\nmessage: {}\n'.format(parents, author, mock_timestamp, message) expected_commit_sha1 = hashlib.sha1(expected_commit_entry.encode()).hexdigest() self.assertEqual(commit_hash, expected_commit_sha1, 'Incorrect commit hash when create the commit') expected_commit_object_path = os.path.join(os.getcwd(), '.git', 'objects', commit_hash[:2], commit_hash[2:]) commit_object_exists = os.path.exists(expected_commit_object_path) self.assertTrue(commit_object_exists)