Example #1
0
    def test_get_remote_head_id(self):
        # For some strange reason jenkins creates a branch called
        # jenkins-<job name> during the build, which makes this test FAIL
        # if we don't take that into account
        if get_current_branch().startswith('jenkins-'):
            raise SkipTest('Workaround for Jenkins Git plugin wierdness.')

        client = GitClient(W3AF_LOCAL_PATH)
        # I don't really want to wait for the local repo to update itself
        # using "git fetch", so I simply put this as a mock
        client.fetch = MagicMock()

        remote_head = client.get_remote_head_id()
        client.fetch.assert_called_once_with()

        self.assertEqual(len(remote_head), 40)
        self.assertIsInstance(remote_head, basestring)

        # Get the ID using an alternative way for double checking
        branch = 'refs/remotes/origin/%s' % get_current_branch()
        proc = subprocess.Popen(['git', 'for-each-ref', branch],
                                stdout=subprocess.PIPE)
        commit_id_line = proc.stdout.readline()
        commit_id_line = commit_id_line.strip()
        commit_id, _ = commit_id_line.split(' ')

        self.assertEqual(remote_head, commit_id)
Example #2
0
 def test_get_remote_head_id(self):
     # For some strange reason jenkins creates a branch called
     # jenkins-<job name> during the build, which makes this test FAIL
     # if we don't take that into account
     if get_current_branch().startswith('jenkins-'):
         raise SkipTest('Workaround for Jenkins Git plugin wierdness.')
     
     client = GitClient(W3AF_LOCAL_PATH)
     # I don't really want to wait for the local repo to update itself
     # using "git fetch", so I simply put this as a mock
     client.fetch = MagicMock()
     
     remote_head = client.get_remote_head_id()
     client.fetch.assert_called_once_with()
             
     self.assertEqual(len(remote_head), 40)
     self.assertIsInstance(remote_head, basestring)
     
     # Get the ID using an alternative way for double checking
     branch = 'refs/remotes/origin/%s' % get_current_branch()
     proc = subprocess.Popen(['git', 'for-each-ref', branch], stdout=subprocess.PIPE)
     commit_id_line = proc.stdout.readline()
     commit_id_line = commit_id_line.strip()
     commit_id, _ = commit_id_line.split(' ')
     
     self.assertEqual(remote_head, commit_id)
Example #3
0
 def test_get_local_head_id(self):
     client = GitClient(W3AF_LOCAL_PATH)
     local_head = client.get_local_head_id()
     
     self.assertEqual(len(local_head), 40)
     self.assertIsInstance(local_head, basestring)
     
     # Get the ID using an alternative way for double checking
     proc = subprocess.Popen(['git', 'log', '-n', '1'], stdout=subprocess.PIPE)
     commit_id_line = proc.stdout.readline()
     commit_id_line = commit_id_line.strip()
     _, commit_id = commit_id_line.split(' ')              
     
     self.assertEqual(local_head, commit_id)
Example #4
0
    def test_get_local_head_id(self):
        client = GitClient(W3AF_LOCAL_PATH)
        local_head = client.get_local_head_id()

        self.assertEqual(len(local_head), 40)
        self.assertIsInstance(local_head, basestring)

        # Get the ID using an alternative way for double checking
        proc = subprocess.Popen(['git', 'log', '-n', '1'],
                                stdout=subprocess.PIPE)
        commit_id_line = proc.stdout.readline()
        commit_id_line = commit_id_line.strip()
        _, commit_id = commit_id_line.split(' ')

        self.assertEqual(local_head, commit_id)
Example #5
0
    def __init__(self, localpath=W3AF_LOCAL_PATH, log=None):
        """
        w3af version manager class. Handles the logic concerning the
        automatic update/commit process of the code.

        :param localpath: Working directory
        :param log: Default output function
        """
        self._localpath = localpath
        self._client = GitClient(localpath)
        self._client.add_observer(self._client_progress)
        
        log = log if log is not None else om.out.console
        self._log = log
        
        # Set default events
        self.register_default_events(log)
        # Startup configuration
        self._start_cfg = StartUpConfig()
Example #6
0
    def test_get_URL(self):
        client = GitClient(W3AF_LOCAL_PATH)

        # https://github.com/andresriancho/w3af/ provides a list of all the
        # URLs which can be used to clone the repo
        REPO_URLS = ('[email protected]:andresriancho/w3af.git',
                     'https://github.com/andresriancho/w3af.git',
                     'git://github.com/andresriancho/w3af.git')

        self.assertIn(client.URL, REPO_URLS)
    def test_update_required_outdated_not_forced(self):
        """
        Test that we check if we're on the latest version if the latest
        local installation update was 3 days ago and the frequency is set to
        daily.
        
        The local repository is NOT in the latest version. A 'git reset --hard'
        is run at the beginning of this test to reset the repo to a revision
        before the latest one.

        *****   WARNING     *****
        *****   WARNING     *****

        YOU DON'T WANT TO RUN THIS TEST WITH OTHERS SINCE IT WILL BREAK THEM!

        *****   WARNING     *****
        *****   WARNING     *****
        """
        try:
            git_client = GitClient('.')
            head_id = git_client.get_local_head_id()
            one_before_head = git_client.get_parent_for_revision(head_id)
            git_client.reset_to_previous_state(one_before_head)

            self.vmgr._start_cfg = start_cfg = StartUpConfig()
            start_cfg._autoupd = True
            start_cfg._freq = StartUpConfig.FREQ_DAILY

            last_upd = datetime.date.today() - datetime.timedelta(days=3)
            start_cfg._lastupd = last_upd

            on_update_check_mock = MagicMock()
            on_already_latest_mock = MagicMock()
            on_update_mock = MagicMock()

            self.vmgr.register(VersionMgr.ON_UPDATE_CHECK,
                               on_update_check_mock, None)
            self.vmgr.register(VersionMgr.ON_ALREADY_LATEST,
                               on_already_latest_mock, None)
            self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

            self.vmgr.callback_onupdate_confirm = MagicMock(side_effect=[
                True,
            ])

            self.vmgr.update()

            self.assertEqual(on_update_check_mock.call_count, 1)
            self.assertEqual(on_already_latest_mock.call_count, 0)
            self.assertEqual(on_update_mock.call_count, 1)
        finally:
            git_client.pull()
    def test_update_required_not_forced(self):
        """
        Test that we check if we're on the latest version if the latest
        local installation update was 3 days ago and the frequency is set to
        daily.
        
        The local repository is in the latest version (git pull is run before)

        In CircleCI this fails with the following message:
            You asked to pull from the remote 'origin', but did not specify
            a branch. Because this is not the default configured remote
            for your current branch, you must specify a branch on the command
            line.
        """
        git_client = GitClient('.')
        git_client.pull()

        self.vmgr._start_cfg = start_cfg = StartUpConfig()
        start_cfg._autoupd = True
        start_cfg._freq = StartUpConfig.FREQ_DAILY

        last_upd = datetime.date.today() - datetime.timedelta(days=3)
        start_cfg._lastupd = last_upd

        on_update_check_mock = MagicMock()
        on_already_latest_mock = MagicMock()
        on_update_mock = MagicMock()

        self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock,
                           None)
        self.vmgr.register(VersionMgr.ON_ALREADY_LATEST,
                           on_already_latest_mock, None)
        self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

        self.vmgr.update()

        self.assertEqual(on_update_check_mock.call_count, 1)
        self.assertEqual(on_already_latest_mock.call_count, 1)
        self.assertEqual(on_update_mock.call_count, 0)
Example #9
0
    def test_update_required_not_forced(self):
        """
        Test that we check if we're on the latest version if the latest
        local installation update was 3 days ago and the frequency is set to
        daily.
        
        The local repository is in the latest version (git pull is run before)

        In CircleCI this fails with the following message:
            You asked to pull from the remote 'origin', but did not specify
            a branch. Because this is not the default configured remote
            for your current branch, you must specify a branch on the command
            line.
        """
        git_client = GitClient('.')
        git_client.pull()
        
        self.vmgr._start_cfg = start_cfg = StartUpConfig()
        start_cfg._autoupd = True
        start_cfg._freq = StartUpConfig.FREQ_DAILY

        last_upd = datetime.date.today() - datetime.timedelta(days=3)
        start_cfg._lastupd = last_upd

        on_update_check_mock = MagicMock()
        on_already_latest_mock = MagicMock()
        on_update_mock = MagicMock()

        self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock, None)
        self.vmgr.register(VersionMgr.ON_ALREADY_LATEST, on_already_latest_mock, None)
        self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

        self.vmgr.update()
        
        self.assertEqual(on_update_check_mock.call_count, 1)
        self.assertEqual(on_already_latest_mock.call_count, 1)
        self.assertEqual(on_update_mock.call_count, 0)
Example #10
0
    def test_update_required_outdated_not_forced(self):
        """
        Test that we check if we're on the latest version if the latest
        local installation update was 3 days ago and the frequency is set to
        daily.
        
        The local repository is NOT in the latest version. A 'git reset --hard'
        is run at the beginning of this test to reset the repo to a revision
        before the latest one.

        *****   WARNING     *****
        *****   WARNING     *****

        YOU DON'T WANT TO RUN THIS TEST WITH OTHERS SINCE IT WILL BREAK THEM!

        *****   WARNING     *****
        *****   WARNING     *****
        """
        try:
            git_client = GitClient('.')
            head_id = git_client.get_local_head_id()
            one_before_head = git_client.get_parent_for_revision(head_id)
            git_client.reset_to_previous_state(one_before_head)
            
            self.vmgr._start_cfg = start_cfg = StartUpConfig()
            start_cfg._autoupd = True
            start_cfg._freq = StartUpConfig.FREQ_DAILY
    
            last_upd = datetime.date.today() - datetime.timedelta(days=3)
            start_cfg._lastupd = last_upd
    
            on_update_check_mock = MagicMock()
            on_already_latest_mock = MagicMock()
            on_update_mock = MagicMock()
    
            self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock, None)
            self.vmgr.register(VersionMgr.ON_ALREADY_LATEST, on_already_latest_mock, None)
            self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None)

            self.vmgr.callback_onupdate_confirm = MagicMock(side_effect=[True,])
    
            self.vmgr.update()
            
            self.assertEqual(on_update_check_mock.call_count, 1)
            self.assertEqual(on_already_latest_mock.call_count, 0)
            self.assertEqual(on_update_mock.call_count, 1)
        finally:
            git_client.pull()
Example #11
0
class VersionMgr(object):
    """
    Perform SVN w3af code update and commit. When an instance is created loads
    data from a .conf file that will be used when actions are executed.
    Also provides some callbacks as well as events to register to.

    Callbacks on:
        UPDATE:
            * callback_onupdate_confirm(msg)
                Return True/False

            * callback_onupdate_show_log(msg, log_func)
                Displays 'msg' to the user and depending on user's answer
                call 'log_func()' which returns a string with the summary of
                the commit logs from the from local revision to repo's.

            * callback_onupdate_error
                If an SVNError occurs this callback is called in order to the
                client class handles the error. Probably notify the user.
        COMMIT:
            {implementation pending}
    Events:
        ON_UPDATE
        ON_UPDATE_ADDED_DEP
        ON_UPDATE_CHECK
        ON_ACTION_ERROR
    """

    # Events constants
    ON_UPDATE = 1
    ON_UPDATE_ADDED_DEP = 2
    ON_UPDATE_CHECK = 3
    ON_ALREADY_LATEST = 4
    ON_ACTION_ERROR = 5
    ON_COMMIT = 6
    ON_PROGRESS = 7

    # Callbacks
    callback_onupdate_confirm = None
    callback_onupdate_show_log = None
    callback_onupdate_error = None

    # Revision constants
    HEAD = 'HEAD'
    BACK = 'BACK'

    def __init__(self, localpath=W3AF_LOCAL_PATH, log=None):
        """
        w3af version manager class. Handles the logic concerning the
        automatic update/commit process of the code.

        :param localpath: Working directory
        :param log: Default output function
        """
        self._localpath = localpath
        self._client = GitClient(localpath)
        self._client.add_observer(self._client_progress)
        
        log = log if log is not None else om.out.console
        self._log = log
        
        # Set default events
        self.register_default_events(log)
        # Startup configuration
        self._start_cfg = StartUpConfig()
    
    def _client_progress(self, op_code, cur_count, max_count, message):
        """
        The GitClient will call this method when it has progress to show
        for fetch() and pull().
        
        Please note that because I don't need it at this moment, I'm simply
        ignoring all parameters and just letting the observers know that this
        event was triggered.
        """
        self._notify(VersionMgr.ON_PROGRESS)
        
    def register_default_events(self, log):
        """
        Default events registration
        
        :param log: Log function to call for events
        :return: None, all saved in self._reg_funcs
        """
        # Registered functions
        self._reg_funcs = {}
        
        msg = ('Checking if a new version is available in our git repository.'
               ' Please wait...')
        self.register(VersionMgr.ON_UPDATE_CHECK, log, msg)
        
        msg = ('Your installation is already on the latest available version.')
        self.register(VersionMgr.ON_ALREADY_LATEST, log, msg)
        
        msg = 'w3af is updating from github.com ...'
        self.register(VersionMgr.ON_UPDATE, log, msg)
        
        msg = ('The third-party dependencies for w3af have changed, please'
               ' exit the framework and run it again to load all changes'
               ' and install any missing modules.')
        self.register(VersionMgr.ON_UPDATE_ADDED_DEP, log, msg)

    def update(self, force=False):
        """
        Perform code update if necessary. Return three elems tuple with the
        ChangeLog of the changed files, the local and the final commit id.

        :param force: Force update ignoring the startup config.
        :return: (changelog: A ChangeLog instance,
                  local_head_id: The local id before the update,
                  commit_id: The commit id after the update)
                  
        """
        if not force and not self._has_to_update():
            # No need to update based on user preferences
            return
        
        # Save the latest update date, always, even when the update had errors
        # or there was no update available
        self._start_cfg.last_upd = date.today()
        self._start_cfg.save()
        
        local_head_id = self._client.get_local_head_id()
        short_local_head_id = to_short_id(local_head_id)
        
        # Lets update!
        self._notify(VersionMgr.ON_UPDATE_CHECK)
        
        # This performs a fetch() which takes time
        remote_head_id = self._client.get_remote_head_id()
        short_remote_head_id = to_short_id(remote_head_id)
        
        if local_head_id == remote_head_id:
            # If local and repo's rev are the same => Nothing to do.
            self._notify(VersionMgr.ON_ALREADY_LATEST)
            return
        
        if self._user_confirmed_update(short_local_head_id, local_head_id,
                                       short_remote_head_id, remote_head_id):
            return self.__update_impl()

    def _user_confirmed_update(self, short_local_head_id, local_head_id,
                                short_remote_head_id, remote_head_id):
        """
        Ask the user if he wants to update or not.
        
        :return: True if the user wants to update.
        """ 
        # Call callback function
        if self.callback_onupdate_confirm is not None:
            
            callback = self.callback_onupdate_confirm
            
            # pylint: disable=E1102
            # pylint: disable=E1103
            msg = 'Your current w3af installation is %s (%s). Do you want '\
                  'to update to %s (%s)?'
            proceed_upd = callback(msg % (short_local_head_id,
                                          get_commit_id_date(local_head_id),
                                          short_remote_head_id,
                                          get_commit_id_date(remote_head_id)))
            
            return proceed_upd
    
    def __update_impl(self):
        """
        Finally call the Git client's pull!
        
        :return: (changelog, local_head_id, target_commit)
        """
        self._notify(VersionMgr.ON_UPDATE)
        
        try:
            changelog = self._client.pull()
        except GitClientError, exc:
            msg = '%s' % exc
            self._notify(VersionMgr.ON_ACTION_ERROR, msg)
            return
        else: