diff --git a/src/pylorax/api/recipes.py b/src/pylorax/api/recipes.py index 5bceefb2..de1e5f62 100644 --- a/src/pylorax/api/recipes.py +++ b/src/pylorax/api/recipes.py @@ -335,14 +335,20 @@ def read_commit(repo, branch, filename, commit=None): :type filename: str :param commit: Optional commit hash :type commit: str - :returns: Contents of the commit - :rtype: str + :returns: The commit id, and the contents of the commit + :rtype: tuple(str, str) :raises: Can raise errors from Ggit If no commit is passed the master:filename is returned, otherwise it will be commit:filename """ - return read_commit_spec(repo, "%s:%s" % (commit or branch, filename)) + if not commit: + # Find the most recent commit for filename on the selected branch + commits = list_commits(repo, branch, filename, 1) + if not commits: + raise RecipeError("No commits for %s on the %s branch." % (filename, branch)) + commit = commits[0].commit + return (commit, read_commit_spec(repo, "%s:%s" % (commit, filename))) def read_recipe_commit(repo, branch, recipe_name, commit=None): """Read a recipe commit from git and return a Recipe object @@ -362,9 +368,30 @@ def read_recipe_commit(repo, branch, recipe_name, commit=None): If no commit is passed the master:filename is returned, otherwise it will be commit:filename """ - recipe_toml = read_commit(repo, branch, recipe_filename(recipe_name), commit) + (_, recipe_toml) = read_commit(repo, branch, recipe_filename(recipe_name), commit) return recipe_from_toml(recipe_toml) +def read_recipe_and_id(repo, branch, recipe_name, commit=None): + """Read a recipe commit and its id from git + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to read + :type recipe_name: str + :param commit: Optional commit hash + :type commit: str + :returns: The commit id, and a Recipe object + :rtype: tuple(str, Recipe) + :raises: Can raise errors from Ggit + + If no commit is passed the master:filename is returned, otherwise it will be + commit:filename + """ + (commit_id, recipe_toml) = read_commit(repo, branch, recipe_filename(recipe_name), commit) + return (commit_id, recipe_from_toml(recipe_toml)) + def list_branch_files(repo, branch): """Return a sorted list of the files on the branch HEAD @@ -671,7 +698,7 @@ class CommitDetails(DataHolder): message = message, revision = revision) -def list_commits(repo, branch, filename): +def list_commits(repo, branch, filename, limit=0): """List the commit history of a file on a branch. :param repo: Open repository @@ -680,6 +707,8 @@ def list_commits(repo, branch, filename): :type branch: str :param filename: filename to revert :type filename: str + :param limit: Number of commits to return (0=all) + :type limit: int :returns: A list of commit details :rtype: list(CommitDetails) :raises: Can raise errors from Ggit @@ -716,6 +745,8 @@ def list_commits(repo, branch, filename): tag = find_commit_tag(repo, branch, filename, commit.get_id()) try: commits.append(get_commit_details(commit, get_revision_from_tag(tag))) + if limit and len(commits) > limit: + break except CommitTimeValError: # Skip any commits that have trouble converting the time # TODO - log details about this failure diff --git a/tests/pylorax/test_recipes.py b/tests/pylorax/test_recipes.py index dfc54a27..50b7a544 100644 --- a/tests/pylorax/test_recipes.py +++ b/tests/pylorax/test_recipes.py @@ -203,6 +203,10 @@ class GitRecipesTest(unittest.TestCase): self.assertNotEqual(recipe, None) self.assertEqual(recipe["name"], "http-server") + # Read the recipe and its commit id + (commit_id, recipe) = recipes.read_recipe_and_id(self.repo, "master", "http-server", commits[0].commit) + self.assertEqual(commit_id, commits[0].commit) + def test_07_tag_commit(self): """Test tagging the most recent commit of a recipe""" result = recipes.tag_file_commit(self.repo, "master", "not-a-file") diff --git a/tests/pylorax/test_server.py b/tests/pylorax/test_server.py index 2f121afd..83b38162 100644 --- a/tests/pylorax/test_server.py +++ b/tests/pylorax/test_server.py @@ -113,7 +113,7 @@ class ServerTestCase(unittest.TestCase): self.assertEqual(data, info_dict_2) info_dict_3 = {"changes":[], - "errors":[{"recipe":"missing-recipe", "msg":"ggit-error: the path 'missing-recipe.toml' does not exist in the given tree (-3)"}], + "errors":[{"recipe":"missing-recipe", "msg":"No commits for missing-recipe.toml on the master branch."}], "recipes":[] } resp = self.server.get("/api/v0/recipes/info/missing-recipe")