Example #1
0
    def updateFromSSH(self, data, connection):
        if self.patchset is None:
            self.patchset = str(data['currentPatchSet']['number'])
        if 'project' not in data:
            raise exceptions.ChangeNotFound(self.number, self.patchset)
        self.project = connection.source.getProject(data['project'])
        self.commit_id = str(data['currentPatchSet']['revision'])
        self.branch = data['branch']
        self.url = data['url']
        urlparse = urllib.parse.urlparse(connection.baseurl)
        baseurl = "%s://%s%s" % (urlparse.scheme, urlparse.netloc,
                                 urlparse.path)
        baseurl = baseurl.rstrip('/')
        self.uris = [
            '%s/%s' % (baseurl, self.number),
            '%s/#/c/%s' % (baseurl, self.number),
            '%s/c/%s/+/%s' % (baseurl, self.project.name, self.number),
        ]

        max_ps = 0
        files = []
        for ps in data['patchSets']:
            if str(ps['number']) == self.patchset:
                self.ref = ps['ref']
                self.commit = ps['revision']
                for f in ps.get('files', []):
                    files.append(f['file'])
            if int(ps['number']) > int(max_ps):
                max_ps = str(ps['number'])
        if max_ps == self.patchset:
            self.is_current_patchset = True
        else:
            self.is_current_patchset = False
        self.files = files
        self.id = data['id']
        self.is_merged = data.get('status', '') == 'MERGED'
        self.approvals = data['currentPatchSet'].get('approvals', [])
        self.open = data['open']
        self.status = data['status']
        self.wip = data.get('wip', False)
        self.owner = data['owner'].get('username')
        self.message = data['commitMessage']

        self.missing_labels = set()
        for sr in data.get('submitRecords', []):
            if sr['status'] == 'NOT_READY':
                for label in sr['labels']:
                    if label['status'] in ['OK', 'MAY']:
                        continue
                    elif label['status'] in ['NEED', 'REJECT']:
                        self.missing_labels.add(label['label'])
Example #2
0
    def _updateChange(self, change, history=None):

        # In case this change is already in the history we have a
        # cyclic dependency and don't need to update ourselves again
        # as this gets done in a previous frame of the call stack.
        # NOTE(jeblair): The only case where this can still be hit is
        # when we get an event for a change with no associated
        # patchset; for instance, when the gerrit topic is changed.
        # In that case, we will update change 1234,None, which will be
        # inserted into the cache as its own entry, but then we will
        # resolve the patchset before adding it to the history list,
        # then if there are dependencies, we can walk down and then
        # back up to the version of this change with a patchset which
        # will match the history list but will have bypassed the
        # change cache because the previous object had a patchset of
        # None.  All paths hit the change cache first.  To be able to
        # drop history, we need to resolve the patchset on events with
        # no patchsets before adding the entry to the change cache.
        if (history and change.number and change.patchset and
            (change.number, change.patchset) in history):
            self.log.debug("Change %s is in history" % (change,))
            return change

        self.log.info("Updating %s" % (change,))
        data = self.query(change.number)
        change._data = data

        if change.patchset is None:
            change.patchset = str(data['currentPatchSet']['number'])
        if 'project' not in data:
            raise exceptions.ChangeNotFound(change.number, change.patchset)
        change.project = self.source.getProject(data['project'])
        change.id = data['id']
        change.branch = data['branch']
        change.url = data['url']
        urlparse = urllib.parse.urlparse(self.baseurl)
        baseurl = "%s%s" % (urlparse.netloc, urlparse.path)
        baseurl = baseurl.rstrip('/')
        change.uris = [
            '%s/%s' % (baseurl, change.number),
            '%s/#/c/%s' % (baseurl, change.number),
        ]

        max_ps = 0
        files = []
        for ps in data['patchSets']:
            if str(ps['number']) == change.patchset:
                change.ref = ps['ref']
                change.commit = ps['revision']
                for f in ps.get('files', []):
                    files.append(f['file'])
            if int(ps['number']) > int(max_ps):
                max_ps = str(ps['number'])
        if max_ps == change.patchset:
            change.is_current_patchset = True
        else:
            change.is_current_patchset = False
        change.files = files

        change.is_merged = self._isMerged(change)
        change.approvals = data['currentPatchSet'].get('approvals', [])
        change.open = data['open']
        change.status = data['status']
        change.owner = data['owner']
        change.message = data['commitMessage']

        if change.is_merged:
            # This change is merged, so we don't need to look any further
            # for dependencies.
            self.log.debug("Updating %s: change is merged" % (change,))
            return change

        if history is None:
            history = []
        else:
            history = history[:]
        history.append((change.number, change.patchset))

        needs_changes = set()
        git_needs_changes = []
        if 'dependsOn' in data:
            parts = data['dependsOn'][0]['ref'].split('/')
            dep_num, dep_ps = parts[3], parts[4]
            self.log.debug("Updating %s: Getting git-dependent change %s,%s" %
                           (change, dep_num, dep_ps))
            dep = self._getChange(dep_num, dep_ps, history=history)
            # This is a git commit dependency. So we only ignore it if it is
            # already merged. So even if it is "ABANDONED", we should not
            # ignore it.
            if (not dep.is_merged) and dep not in needs_changes:
                git_needs_changes.append(dep)
                needs_changes.add(dep)
        change.git_needs_changes = git_needs_changes

        compat_needs_changes = []
        for record in self._getDependsOnFromCommit(data['commitMessage'],
                                                   change):
            dep_num = str(record['number'])
            dep_ps = str(record['currentPatchSet']['number'])
            self.log.debug("Updating %s: Getting commit-dependent "
                           "change %s,%s" %
                           (change, dep_num, dep_ps))
            dep = self._getChange(dep_num, dep_ps, history=history)
            if dep.open and dep not in needs_changes:
                compat_needs_changes.append(dep)
                needs_changes.add(dep)
        change.compat_needs_changes = compat_needs_changes

        needed_by_changes = set()
        git_needed_by_changes = []
        if 'neededBy' in data:
            for needed in data['neededBy']:
                parts = needed['ref'].split('/')
                dep_num, dep_ps = parts[3], parts[4]
                self.log.debug("Updating %s: Getting git-needed change %s,%s" %
                               (change, dep_num, dep_ps))
                dep = self._getChange(dep_num, dep_ps, history=history)
                if (dep.open and dep.is_current_patchset and
                    dep not in needed_by_changes):
                    git_needed_by_changes.append(dep)
                    needed_by_changes.add(dep)
        change.git_needed_by_changes = git_needed_by_changes

        compat_needed_by_changes = []
        for record in self._getNeededByFromCommit(data['id'], change):
            dep_num = str(record['number'])
            dep_ps = str(record['currentPatchSet']['number'])
            self.log.debug("Updating %s: Getting commit-needed change %s,%s" %
                           (change, dep_num, dep_ps))
            # Because a commit needed-by may be a cross-repo
            # dependency, cause that change to refresh so that it will
            # reference the latest patchset of its Depends-On (this
            # change). In case the dep is already in history we already
            # refreshed this change so refresh is not needed in this case.
            refresh = (dep_num, dep_ps) not in history
            dep = self._getChange(
                dep_num, dep_ps, refresh=refresh, history=history)
            if (dep.open and dep.is_current_patchset
                and dep not in needed_by_changes):
                compat_needed_by_changes.append(dep)
                needed_by_changes.add(dep)
        change.compat_needed_by_changes = compat_needed_by_changes

        self.sched.onChangeUpdated(change)

        return change
Example #3
0
    def _updateChange(self, change, history=None):
        self.log.info("Updating %s" % (change, ))
        data = self.connection.query(change.number)
        change._data = data

        if change.patchset is None:
            change.patchset = str(data['currentPatchSet']['number'])

        if 'project' not in data:
            found = False
            start = time.time()
            while time.time() - start < 75:
                self.log.info("Change %s not found, retrying" % (change, ))
                data = self.connection.query(change.number)
                self.log.debug("Change replication retry debug: %s" % data)
                if 'project' in data:
                    found = True
                    break
                time.sleep(self.replication_retry_interval)
            if not found:
                raise exceptions.ChangeNotFound(change.number, change.patchset)
            change._data = data

        change.project = self.sched.getProject(data['project'])
        change.branch = data['branch']
        change.url = data['url']
        max_ps = 0
        files = []
        for ps in data['patchSets']:
            if int(ps['number']) == int(change.patchset):
                change.refspec = ps['ref']
                for f in ps.get('files', []):
                    files.append(f['file'])
            if int(ps['number']) > int(max_ps):
                max_ps = ps['number']
        if int(max_ps) == int(change.patchset):
            change.is_current_patchset = True
        else:
            change.is_current_patchset = False
        change.files = files

        change.is_merged = self._isMerged(change)
        change.approvals = data['currentPatchSet'].get('approvals', [])
        change.open = data['open']
        change.status = data['status']
        change.owner = data['owner']
        change.wip = data.get('wip', False)
        change.private = data.get('private', False)

        if change.is_merged:
            # This change is merged, so we don't need to look any further
            # for dependencies.
            self.log.debug("Updating %s: change is merged" % (change, ))
            return change

        if history is None:
            history = []
        else:
            history = history[:]
        history.append(change.number)

        needs_changes = []
        if 'dependsOn' in data:
            parts = data['dependsOn'][0]['ref'].split('/')
            dep_num, dep_ps = parts[3], parts[4]
            if dep_num in history:
                raise Exception("Dependency cycle detected: %s in %s" %
                                (dep_num, history))
            self.log.debug("Updating %s: Getting git-dependent change %s,%s" %
                           (change, dep_num, dep_ps))
            dep = self._getChange(dep_num, dep_ps, history=history)
            # Because we are not forcing a refresh in _getChange, it
            # may return without executing this code, so if we are
            # updating our change to add ourselves to a dependency
            # cycle, we won't detect it.  By explicitly performing a
            # walk of the dependency tree, we will.
            detect_cycle(dep, history)
            # This is a git commit dependency. So we only ignore it if it is
            # already merged. So even if it is "ABANDONED", we should not
            # ignore it.
            if (not dep.is_merged) and dep not in needs_changes:
                needs_changes.append(dep)

        for record in self._getDependsOnFromCommit(data['commitMessage'],
                                                   change):
            dep_num = record['number']
            dep_ps = record['currentPatchSet']['number']
            if dep_num in history:
                raise Exception("Dependency cycle detected: %s in %s" %
                                (dep_num, history))
            self.log.debug("Updating %s: Getting commit-dependent "
                           "change %s,%s" % (change, dep_num, dep_ps))
            dep = self._getChange(dep_num, dep_ps, history=history)
            # Because we are not forcing a refresh in _getChange, it
            # may return without executing this code, so if we are
            # updating our change to add ourselves to a dependency
            # cycle, we won't detect it.  By explicitly performing a
            # walk of the dependency tree, we will.
            detect_cycle(dep, history)
            if dep.open and dep not in needs_changes:
                needs_changes.append(dep)
        change.needs_changes = needs_changes

        needed_by_changes = []
        if 'neededBy' in data:
            for needed in data['neededBy']:
                parts = needed['ref'].split('/')
                dep_num, dep_ps = parts[3], parts[4]
                self.log.debug("Updating %s: Getting git-needed change %s,%s" %
                               (change, dep_num, dep_ps))
                dep = self._getChange(dep_num, dep_ps)
                if dep.open and dep.is_current_patchset:
                    needed_by_changes.append(dep)

        for record in self._getNeededByFromCommit(data['id'], change):
            dep_num = record['number']
            dep_ps = record['currentPatchSet']['number']
            self.log.debug("Updating %s: Getting commit-needed change %s,%s" %
                           (change, dep_num, dep_ps))
            # Because a commit needed-by may be a cross-repo
            # dependency, cause that change to refresh so that it will
            # reference the latest patchset of its Depends-On (this
            # change).
            dep = self._getChange(dep_num, dep_ps, refresh=True)
            if dep.open and dep.is_current_patchset:
                needed_by_changes.append(dep)
        change.needed_by_changes = needed_by_changes

        return change
Example #4
0
    def _updateChange(self, change, history=None):
        self.log.info("Updating information for %s,%s" %
                      (change.number, change.patchset))
        data = self.connection.query(change.number)
        change._data = data

        if change.patchset is None:
            change.patchset = data['currentPatchSet']['number']

        if 'project' not in data:
            raise exceptions.ChangeNotFound(change.number, change.patchset)
        # If updated changed came as a dependent on
        # and its project is not defined,
        # then create a 'foreign' project for it in layout
        change.project = self.sched.getProject(data['project'],
                                               create_foreign=bool(history))
        change.branch = data['branch']
        change.url = data['url']
        max_ps = 0
        files = []
        for ps in data['patchSets']:
            if ps['number'] == change.patchset:
                change.refspec = ps['ref']
                for f in ps.get('files', []):
                    files.append(f['file'])
            if int(ps['number']) > int(max_ps):
                max_ps = ps['number']
        if max_ps == change.patchset:
            change.is_current_patchset = True
        else:
            change.is_current_patchset = False
        change.files = files

        change.is_merged = self._isMerged(change)
        change.approvals = data['currentPatchSet'].get('approvals', [])
        change.open = data['open']
        change.status = data['status']
        change.owner = data['owner']

        if change.is_merged:
            # This change is merged, so we don't need to look any further
            # for dependencies.
            return change

        if history is None:
            history = []
        else:
            history = history[:]
        history.append(change.number)

        needs_changes = []
        if 'dependsOn' in data:
            parts = data['dependsOn'][0]['ref'].split('/')
            dep_num, dep_ps = parts[3], parts[4]
            if dep_num in history:
                raise Exception("Dependency cycle detected: %s in %s" %
                                (dep_num, history))
            self.log.debug("Getting git-dependent change %s,%s" %
                           (dep_num, dep_ps))
            dep = self._getChange(dep_num, dep_ps, history=history)
            if (not dep.is_merged) and dep not in needs_changes:
                needs_changes.append(dep)

        for record in self._getDependsOnFromCommit(data['commitMessage']):
            dep_num = record['number']
            dep_ps = record['currentPatchSet']['number']
            if dep_num in history:
                raise Exception("Dependency cycle detected: %s in %s" %
                                (dep_num, history))
            self.log.debug("Getting commit-dependent change %s,%s" %
                           (dep_num, dep_ps))
            dep = self._getChange(dep_num, dep_ps, history=history)
            if (not dep.is_merged) and dep not in needs_changes:
                needs_changes.append(dep)
        change.needs_changes = needs_changes

        needed_by_changes = []
        if 'neededBy' in data:
            for needed in data['neededBy']:
                parts = needed['ref'].split('/')
                dep_num, dep_ps = parts[3], parts[4]
                dep = self._getChange(dep_num, dep_ps)
                if (not dep.is_merged) and dep.is_current_patchset:
                    needed_by_changes.append(dep)

        for record in self._getNeededByFromCommit(data['id']):
            dep_num = record['number']
            dep_ps = record['currentPatchSet']['number']
            self.log.debug("Getting commit-needed change %s,%s" %
                           (dep_num, dep_ps))
            # Because a commit needed-by may be a cross-repo
            # dependency, cause that change to refresh so that it will
            # reference the latest patchset of its Depends-On (this
            # change).
            dep = self._getChange(dep_num, dep_ps, refresh=True)
            if (not dep.is_merged) and dep.is_current_patchset:
                needed_by_changes.append(dep)
        change.needed_by_changes = needed_by_changes

        return change