Skip to content

Commit

Permalink
Merge pull request #274 from Erich-McMillan/users/erich/implement-#98
Browse files Browse the repository at this point in the history
Issue#98 Allow user to specify locking to specific rev
  • Loading branch information
jacebrowning committed Mar 9, 2022
2 parents c00f7c6 + 232b6ee commit e912553
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 4 deletions.
8 changes: 8 additions & 0 deletions docs/interfaces/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ with optional arguments:
- `*names`: optional list of dependency source or group names to filter on
- `root`: specifies the path to the root working tree

with specific revision per source:

- Each item in name may be followed by @git_rev or @git_branch or @git_tag.
- Example:
- `*names = ["<source1>@<sha_rev>", <source2>@<tag>", "<source3>"]`.
- Source1 and source2 will be locked to sha_rev and tag if they exist in the repository,
source3 will be locked to the currently checked out revision.

## Uninstall

To delete all dependencies, call:
Expand Down
10 changes: 10 additions & 0 deletions docs/interfaces/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,16 @@ To restore the exact versions previously checked out, run:
$ gitman install
```

To lock a source to a specific revision
```
$gitman lock <name1>@<sha_rev>
```

To lock a source to latest revision of a specific tag or branch
```
$gitman lock <name1>@<git_tag_or_branch>
```

## Uninstall

To delete all dependencies, run:
Expand Down
4 changes: 3 additions & 1 deletion gitman/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ def init(*, force: bool = False):
rev="master",
)
config.sources.append(source)
source = source.lock(rev="ebbbf773431ba07510251bb03f9525c7bab2b13a")
source = source.lock(
rev="ebbbf773431ba07510251bb03f9525c7bab2b13a", verify_rev=False
)
config.sources_locked.append(source)
config.datafile.save()

Expand Down
13 changes: 13 additions & 0 deletions gitman/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,19 @@ def get_branch():
return git("rev-parse", "--abbrev-ref", "HEAD", _show=False)[0]


def get_object_rev(object_name):
"""Get the revision associated with the object specified."""
log_results = git("log", "-n", "1", object_name, _show=False, _ignore=True)

commit_sha = None

if len(log_results) > 0:
if "commit" in log_results[0]:
commit_sha = log_results[0].replace("commit ", "")

return commit_sha


def _get_sha_from_rev(rev):
"""Get a rev-parse string's hash."""
if "@{" in rev:
Expand Down
36 changes: 34 additions & 2 deletions gitman/models/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,40 @@ def run_scripts(self, *names, depth=None, force=False, show_shell_stdout=False):

return count

@classmethod
def _split_name_and_rev(cls, name_rev):
true_name = name_rev
rev = None
if "@" in name_rev:
name_split = name_rev.split("@")
true_name = name_split[0]
rev = name_split[1]
return true_name, rev

@classmethod
def _remap_names_and_revs(cls, names):

name_rev_map = {}

for name in names:
base_name, rev = cls._split_name_and_rev(name)
name_rev_map[base_name] = rev

return name_rev_map.keys(), name_rev_map

def lock_dependencies(self, *names, obey_existing=True, skip_changes=False):
"""Lock down the immediate dependency versions."""
sources_to_install, source_to_install_revs = self._remap_names_and_revs(
[*names]
)
sources = self._get_sources(use_locked=obey_existing).copy()

skip_default = True
if len(sources_to_install) == 0:
skip_default = False

sources_filter = self._get_sources_filter(
*names, sources=sources, skip_default_group=False
*sources_to_install, sources=sources, skip_default_group=skip_default
)

shell.cd(self.location_path)
Expand All @@ -197,7 +226,10 @@ def lock_dependencies(self, *names, obey_existing=True, skip_changes=False):
log.info("Skipped dependency: %s", source.name)
continue

source_locked = source.lock(skip_changes=skip_changes)
rev = None
if source.name in source_to_install_revs.keys():
rev = source_to_install_revs[source.name]
source_locked = source.lock(skip_changes=skip_changes, rev=rev)

if source_locked is not None:
try:
Expand Down
9 changes: 8 additions & 1 deletion gitman/models/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def identify(self, allow_dirty=True, allow_missing=True, skip_changes=False):

raise self._invalid_repository

def lock(self, rev=None, allow_dirty=False, skip_changes=False):
def lock(self, rev=None, allow_dirty=False, skip_changes=False, verify_rev=True):
"""Create a locked source object.
Return a locked version of the current source if not dirty
Expand All @@ -231,6 +231,13 @@ def lock(self, rev=None, allow_dirty=False, skip_changes=False):
_, _, rev = self.identify(
allow_dirty=allow_dirty, allow_missing=False, skip_changes=skip_changes
)
elif verify_rev:
shell.cd(self.name)
rev_tmp = rev
rev = git.get_object_rev(rev)
if rev is None:
log.error(f"No commit found for {rev_tmp} in source {self.name}")
return None

if rev == self.DIRTY:
return None
Expand Down
24 changes: 24 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1300,3 +1300,27 @@ def it_should_fail_on_invalid_repositories(config):

finally:
shell.rm(os.path.join("deps", "gitman_1"))

def it_should_lock_repository_to_user_specified_rev(config):
expect(gitman.update(depth=1, lock=False)) == True

expect(gitman.lock("gitman_1@master")) == True
config.datafile.load()
expect(config.datafile.text).contains(
"63ddfd82d308ddae72d31b61cb8942c898fa05b5"
)

def it_should_lock_repository_to_latest_rev_in_user_specified_reference(config):
expect(gitman.update(depth=1, lock=False)) == True

expect(gitman.lock("gitman_1@63ddfd82d308ddae72d31b61cb8942c898fa05b5")) == True

config.datafile.load()
expect(config.datafile.text).contains(
"63ddfd82d308ddae72d31b61cb8942c898fa05b5"
)

def it_should_skip_lock_to_invalid_user_specified_reference(config):
expect(gitman.update(depth=1, lock=False)) == True

expect(gitman.lock("gitman_1@deadbeef_ref")) == False

0 comments on commit e912553

Please sign in to comment.