示例#1
0
def new_update(ref_name, old_rev, new_rev, all_refs, submitter_email):
    """Return the correct object for the given parameters.

    PARAMETERS
        See AbstractUpdate.__init__.

    RETURN VALUE
        An object of the correct AbstractUpdate (child) class.
    """
    # At least one of the references must be non-null...
    assert not (is_null_rev(old_rev) and is_null_rev(new_rev))

    if is_null_rev(old_rev):
        change_type = CREATE
        object_type = get_object_type(new_rev)
    elif is_null_rev(new_rev):
        change_type = DELETE
        object_type = get_object_type(old_rev)
    else:
        change_type = UPDATE
        object_type = get_object_type(new_rev)

    new_cls = None
    for key in REF_CHANGE_MAP:
        (map_ref_prefix, map_change_type, map_object_type) = key
        if ((change_type == map_change_type
             and object_type == map_object_type
             and ref_name.startswith(map_ref_prefix))):
            new_cls = REF_CHANGE_MAP[key]
            break
    if new_cls is None:
        return None

    return new_cls(ref_name, old_rev, new_rev, all_refs,
                   submitter_email)
示例#2
0
def new_update(ref_name, old_rev, new_rev, all_refs, submitter_email):
    """Return the correct object for the given parameters.

    PARAMETERS
        See AbstractUpdate.__init__.

    RETURN VALUE
        An object of the correct AbstractUpdate (child) class.
    """
    # At least one of the references must be non-null...
    assert not (is_null_rev(old_rev) and is_null_rev(new_rev))

    if is_null_rev(old_rev):
        change_type = CREATE
        object_type = get_object_type(new_rev)
    elif is_null_rev(new_rev):
        change_type = DELETE
        object_type = get_object_type(old_rev)
    else:
        change_type = UPDATE
        object_type = get_object_type(new_rev)

    new_cls = None
    for key in REF_CHANGE_MAP:
        (map_ref_prefix, map_change_type, map_object_type) = key
        if ((change_type == map_change_type
             and object_type == map_object_type
             and ref_name.startswith(map_ref_prefix))):
            new_cls = REF_CHANGE_MAP[key]
            break
    if new_cls is None:
        return None

    return new_cls(ref_name, old_rev, new_rev, all_refs,
                   submitter_email)
示例#3
0
def check_update(ref_name, old_rev, new_rev):
    """General handler of the given update.

    Raises InvalidUpdate if the update cannot be accepted (usually
    because one of the commits fails a style-check, for instance).

    PARAMETERS
        ref_name: The name of the reference being update (Eg:
            refs/heads/master).
        old_rev: The commit SHA1 of the reference before the update.
        new_rev: The new commit SHA1 that the reference will point to
            if the update is accepted.

    REMARKS
        This function assumes that scratch_dir has been initialized.
    """
    debug('check_update(ref_name=%s, old_rev=%s, new_rev=%s)'
          % (ref_name, old_rev, new_rev),
          level=2)
    update_cls = new_update(ref_name, old_rev, new_rev, git_show_ref(),
                            submitter_email=None)
    if update_cls is None:
        raise InvalidUpdate(
            "This type of update (%s,%s) is currently unsupported."
            % (ref_name, get_object_type(new_rev)))
    with FileLock('git-hooks::update.token'):
        update_cls.validate()
示例#4
0
文件: test.py 项目: simark/git-hooks
    def test_get_object_type_null_rev(self):
        """Unit test get_object_type with a null SHA1."""
        self.enable_unit_test()

        from git import get_object_type

        object_type = get_object_type(
            '0000000000000000000000000000000000000000')
        self.assertEqual(object_type, 'delete')
示例#5
0
def new_update(ref_name, old_rev, new_rev, all_refs, submitter_email):
    """Return the correct object for the given parameters.

    PARAMETERS
        See AbstractUpdate.__init__.

    RETURN VALUE
        An object of the correct AbstractUpdate (child) class.
    """
    if is_null_rev(old_rev) and is_null_rev(new_rev):
        # This happens when the user is trying to delete a specific
        # reference which does not exist in the repository.
        #
        # Note that this seems to only happen when the user passes
        # the full reference name in the delete-push. When using
        # a branch name (i.e. 'master' instead of 'refs/heads/master'),
        # git itself notices that the branch doesn't exist and returns
        # an error even before calling the hooks for validation.
        raise InvalidUpdate(
            "unable to delete '{}': remote ref does not exist".format(
                ref_name))

    if is_null_rev(old_rev):
        change_type = UpdateKind.create
        object_type = get_object_type(new_rev)
    elif is_null_rev(new_rev):
        change_type = UpdateKind.delete
        object_type = get_object_type(old_rev)
    else:
        change_type = UpdateKind.update
        object_type = get_object_type(new_rev)

    ref_kind = get_ref_kind(ref_name)
    if ref_kind is None:
        raise_unrecognized_ref_name(ref_name)

    new_cls = REF_CHANGE_MAP.get((ref_kind, change_type, object_type), None)
    if new_cls is None:
        return None

    return new_cls(ref_name, ref_kind, object_type, old_rev, new_rev, all_refs,
                   submitter_email)
示例#6
0
    def __init__(self, ref_name, old_rev, new_rev, all_refs,
                 submitter_email):
        """The constructor.

        Also calls self.auto_sanity_check() at the end.

        PARAMETERS
            ref_name: Same as the attribute.
            old_rev: Same as the attribute.
            new_rev: Same as the attribute.
            all_refs: Same as the attribute.
            submitter_email: Same as parameter from_email in class
                EmailInfo's constructor.
                This is used to override the default "from" email when
                the user sending the emails is different from the user
                that pushed/submitted the update.
        """
        # If the repository's configuration does not provide
        # the minimum required to email update notifications,
        # refuse the update.
        if not git_config('hooks.mailinglist'):
            raise InvalidUpdate(
                'Error: hooks.mailinglist config option not set.',
                'Please contact your repository\'s administrator.')

        m = re.match(r"([^/]+/[^/]+)/(.+)", ref_name)

        self.ref_name = ref_name
        self.short_ref_name = m.group(2) if m else ref_name
        self.ref_namespace = m.group(1) if m else None
        self.old_rev = old_rev
        self.new_rev = new_rev
        self.new_rev_type = get_object_type(self.new_rev)
        self.all_refs = all_refs
        self.email_info = EmailInfo(email_from=submitter_email)

        # Implement the added_commits "attribute" as a property,
        # to allow for initialization only on-demand. This allows
        # us to avoid computing this list until the moment we
        # actually need it. To help caching its value, avoiding
        # the need to compute it multiple times, we introduce
        # a private attribute named __added_commits.
        #
        # Same treatment for the lost_commits "attribute".
        self.__added_commits = None
        self.__lost_commits = None

        self.self_sanity_check()
示例#7
0
    def __init__(self, ref_name, old_rev, new_rev, all_refs, submitter_email):
        """The constructor.

        Also calls self.auto_sanity_check() at the end.

        PARAMETERS
            ref_name: Same as the attribute.
            old_rev: Same as the attribute.
            new_rev: Same as the attribute.
            all_refs: Same as the attribute.
            submitter_email: Same as parameter from_email in class
                EmailInfo's constructor.
                This is used to override the default "from" email when
                the user sending the emails is different from the user
                that pushed/submitted the update.
        """
        # If the repository's configuration does not provide
        # the minimum required to email update notifications,
        # refuse the update.
        if not git_config('hooks.mailinglist'):
            raise InvalidUpdate(
                'Error: hooks.mailinglist config option not set.',
                'Please contact your repository\'s administrator.')

        m = re.match(r"([^/]+/[^/]+)/(.+)", ref_name)

        self.ref_name = ref_name
        self.short_ref_name = m.group(2) if m else ref_name
        self.ref_namespace = m.group(1) if m else None
        self.old_rev = old_rev
        self.new_rev = new_rev
        self.new_rev_type = get_object_type(self.new_rev)
        self.all_refs = all_refs
        self.email_info = EmailInfo(email_from=submitter_email)

        # Implement the added_commits "attribute" as a property,
        # to allow for initialization only on-demand. This allows
        # us to avoid computing this list until the moment we
        # actually need it. To help caching its value, avoiding
        # the need to compute it multiple times, we introduce
        # a private attribute named __added_commits.
        #
        # Same treatment for the lost_commits "attribute".
        self.__added_commits = None
        self.__lost_commits = None

        self.self_sanity_check()
示例#8
0
def check_update(ref_name, old_rev, new_rev):
    """General handler of the given update.

    Raises InvalidUpdate if the update cannot be accepted (usually
    because one of the commits fails a style-check, for instance).

    PARAMETERS
        ref_name: The name of the reference being update (Eg:
            refs/heads/master).
        old_rev: The commit SHA1 of the reference before the update.
        new_rev: The new commit SHA1 that the reference will point to
            if the update is accepted.

    REMARKS
        This function assumes that scratch_dir has been initialized.
    """
    debug(
        "check_update(ref_name=%s, old_rev=%s, new_rev=%s)"
        % (ref_name, old_rev, new_rev),
        level=2,
    )

    check_minimum_system_requirements()

    # Do nothing if the reference is in the hooks.ignore-refs list.
    ignore_refs_match = utils.search_config_option_list("hooks.ignore-refs", ref_name)
    if ignore_refs_match is not None:
        debug(f"{ref_name} ignored due to hooks.ignore-refs" f" ({ignore_refs_match})")
        return

    update_cls = new_update(
        ref_name, old_rev, new_rev, git_show_ref(), submitter_email=None
    )
    if update_cls is None:
        # Report an error. We could look more precisely into what
        # might be the reason behind this error, and print more precise
        # diagnostics, but it does not seem like this would be worth
        # the effort: It requires some pretty far-fetched scenarios
        # for this to trigger; so, this should happen only very seldomly,
        # and when a user does something very unusual.
        raise InvalidUpdate(
            "This type of update (%s,%s) is not valid."
            % (ref_name, get_object_type(new_rev))
        )
    with FileLock("git-hooks::update.token"):
        update_cls.validate()
        maybe_update_hook(ref_name, old_rev, new_rev)
示例#9
0
from git import git, get_object_type

print("DEBUG: Test the git --switch=False attribute")
print(git.log("-n1", pretty="format:%P", _decode=True).strip())

print("DEBUG: A Test to verify that git does not do any lstrip-ing...")
print(git.log("-n1", "space-subject", pretty="format:%s", _decode=True))

print("DEBUG: Unit test get_object_type with a null SHA1...")
print(get_object_type("0000000000000000000000000000000000000000"))