Example #1
0
    def get_last_code_date(self):
        """
        Return the time (in seconds since epoch) when code was last modified in
        this sandbox. If code is pristine (hasn't changed from what's checked
        in), None is returned.
        """
        when_since_epoch = 0
        cr = self.get_code_root()
        # I know I could do the list comprehensions below in a single step, but
        # I want to make this debuggable and do it in stages.
        code_components = os.listdir(cr)
        code_components = [cr + cc for cc in code_components]
        code_components = [cc for cc in code_components if os.path.isdir(cc + "/.bzr")]

        def potentially_changed_file(lbl):
            return lbl == "modified" or lbl == "unknown"

        for cc in code_components:
            status = vcs.get_status(cc, status_filter=potentially_changed_file)
            if status:
                for k in status.keys():
                    for m in status[k]:
                        try:
                            lastmod = os.stat(cc + "/" + m).st_mtime
                            if lastmod > when_since_epoch:
                                when_since_epoch = lastmod
                        except:
                            pass
        if not when_since_epoch:
            when_since_epoch = None
        return when_since_epoch
Example #2
0
def get_component_status(comp,
                         sb,
                         status_filter=None,
                         aspect_filter=None,
                         revision=None):
    '''
    Return a dictionary describing all files/folders with notable status within
    the specified component.

    Dictionary format: key = an aspect of the component ("code", "test",
    or "built"); value = sub-dictionary of notable status items. Sub-dictionary
    format: key = status label like "modified" or "unknown"; value = a list of
    paths, relative to the component's folder in the <aspect> root, of files
    with the specified status.

    @param status_filter A function that decides whether a particular status
    label is interesting. Takes a string and returns a boolean.

    @param aspect_filter A function that decides whether a particular aspect is
    interesting. Takes a string and returns a boolean.
    '''
    status = {}
    # Iterate over all aspects of the component that exist and are tied to vcs.
    for a in get_vcs_component_aspects(comp, sb):
        path = sb.get_component_path(comp, a)
        if (not aspect_filter) or aspect_filter(a):
            x = vcs.get_status(path,
                               status_filter=status_filter,
                               revision=revision)
            if x:
                status[a] = x
    return status
Example #3
0
def update_program_if_needed(silent=False):
    '''
    See if sadm itself needs to be updated.
    '''
    # Don't do anything if we're running from within a sandbox.
    if sandbox.find_root_from_within(APP_FOLDER):
        return
    # If this folder has any kind of relationship with a repo...
    if vcs.folder_is_tied_to_vcs(APP_FOLDER):
        try:
            status = vcs.get_status(APP_FOLDER, status_filter=lambda lbl: lbl!= 'unknown', revision=-1)
        except:
            eprintc("Status of sadm can't be determined (is the network down?). Skipping update.", WARNING_COLOR)
            return
        if status:
            # See if there are any items at a status that will prevent success of update.
            bad_status = [x for x in status.keys() if x not in 'modified|removed|added|renamed|kind changed']
            if bad_status:
                eprintc('''
The master version of sadm has changed, but automatic update is impossible. Do
a manual bzr up to resolve the following issues:
''', ERROR_COLOR)
                print(aggregate_vcs.format_aspect_status(None, None, "sadm", status))
                return
            err = vcs.update_checkout(APP_FOLDER)
            if err:
                print('Unable to update sadm; exit code %d from "bzr up" command. Try running "bzr up" manually.' % err)
                return
            return True
        elif not silent:
            print("Sadm is up to date.")
    else:
        if not silent:
            print("This copy of %s doesn't run from a directory that's connected to bzr." % APP_CMD)
Example #4
0
def get_component_status(comp, sb, status_filter=None, aspect_filter=None, revision=None):
    '''
    Return a dictionary describing all files/folders with notable status within
    the specified component.

    Dictionary format: key = an aspect of the component ("code", "test",
    or "built"); value = sub-dictionary of notable status items. Sub-dictionary
    format: key = status label like "modified" or "unknown"; value = a list of
    paths, relative to the component's folder in the <aspect> root, of files
    with the specified status.

    @param status_filter A function that decides whether a particular status
    label is interesting. Takes a string and returns a boolean.

    @param aspect_filter A function that decides whether a particular aspect is
    interesting. Takes a string and returns a boolean.
    '''
    status = {}
    # Iterate over all aspects of the component that exist and are tied to vcs.
    for a in get_vcs_component_aspects(comp, sb):
        path = sb.get_component_path(comp, a)
        if (not aspect_filter) or aspect_filter(a):
            x = vcs.get_status(path, status_filter=status_filter, revision=revision)
            if x:
                status[a] = x
    return status
Example #5
0
    def get_last_code_date(self):
        '''
        Return the time (in seconds since epoch) when code was last modified in
        this sandbox. If code is pristine (hasn't changed from what's checked
        in), None is returned.
        '''
        when_since_epoch = 0
        cr = self.get_code_root()
        # I know I could do the list comprehensions below in a single step, but
        # I want to make this debuggable and do it in stages.
        code_components = os.listdir(cr)
        code_components = [cr + cc for cc in code_components]
        code_components = [
            cc for cc in code_components if os.path.isdir(cc + '/.bzr')
        ]

        def potentially_changed_file(lbl):
            return lbl == 'modified' or lbl == 'unknown'

        for cc in code_components:
            status = vcs.get_status(cc, status_filter=potentially_changed_file)
            if status:
                for k in status.keys():
                    for m in status[k]:
                        try:
                            lastmod = os.stat(cc + '/' + m).st_mtime
                            if lastmod > when_since_epoch:
                                when_since_epoch = lastmod
                        except:
                            pass
        if not when_since_epoch:
            when_since_epoch = None
        return when_since_epoch
Example #6
0
def add_new_files(sb, folder_to_publish):
    status = vcs.get_status(folder_to_publish, status_filter=_bzr_status_is_interesting)
    if 'conflicted' in status:
        vprint('Conflicting items; publish requires manual intervention.')
        vprint('  ' + '\n  '.join(status['conflicted']))
        return 1
    if 'unknown' in status:
        vprint('Adding new files.', verbosity=1)
        cmd = 'bzr add'
        vprint(cmd, verbosity=2)
        err = os.system(cmd)
        if err:
            return err
    return 0
Example #7
0
def update_program_if_needed(silent=False):
    '''
    See if sadm itself needs to be updated.
    '''
    # Don't do anything if we're running from within a sandbox.
    if sandbox.find_root_from_within(APP_FOLDER):
        return
    # If this folder has any kind of relationship with a repo...
    if vcs.folder_is_tied_to_vcs(APP_FOLDER):
        try:
            status = vcs.get_status(APP_FOLDER,
                                    status_filter=lambda lbl: lbl != 'unknown',
                                    revision=-1)
        except:
            eprintc(
                "Status of sadm can't be determined (is the network down?). Skipping update.",
                WARNING_COLOR)
            return
        if status:
            # See if there are any items at a status that will prevent success of update.
            bad_status = [
                x for x in status.keys()
                if x not in 'modified|removed|added|renamed|kind changed'
            ]
            if bad_status:
                eprintc(
                    '''
The master version of sadm has changed, but automatic update is impossible. Do
a manual bzr up to resolve the following issues:
''', ERROR_COLOR)
                print(
                    aggregate_vcs.format_aspect_status(None, None, "sadm",
                                                       status))
                return
            err = vcs.update_checkout(APP_FOLDER)
            if err:
                print(
                    'Unable to update sadm; exit code %d from "bzr up" command. Try running "bzr up" manually.'
                    % err)
                return
            return True
        elif not silent:
            print("Sadm is up to date.")
    else:
        if not silent:
            print(
                "This copy of %s doesn't run from a directory that's connected to bzr."
                % APP_CMD)
Example #8
0
def checkin_component(msg, comp, sb, validate_status=True):
    if validate_status:
        bad_status = get_component_status(comp, status_filter=_items_that_wont_checkin)
        if bad_status:
            print(format_component_status(sb, bad_status))
            print('Some items are not ready for checkin.')
            return
    aspects = get_vcs_component_aspects(comp, sb)
    for a in aspects:
        if a.startswith(component.BUILT_ASPECT_NAME):
            continue
        path = sb.get_component_path(comp, a)
        if vcs.get_status(path):
            try:
                x = vcs.checkin(path, msg)
            except:
                print(sys.exc_info()[1])
Example #9
0
def checkin_component(msg, comp, sb, validate_status=True):
    if validate_status:
        bad_status = get_component_status(
            comp, status_filter=_items_that_wont_checkin)
        if bad_status:
            print(format_component_status(sb, bad_status))
            print('Some items are not ready for checkin.')
            return
    aspects = get_vcs_component_aspects(comp, sb)
    for a in aspects:
        if a.startswith(component.BUILT_ASPECT_NAME):
            continue
        path = sb.get_component_path(comp, a)
        if vcs.get_status(path):
            try:
                x = vcs.checkin(path, msg)
            except:
                print(sys.exc_info()[1])
Example #10
0
def report(sb, state):
    rr = sb.get_report_root()
    root = sb.get_root()
    need_checkin = vcs.folder_is_tied_to_vcs(rr)
    try:
        # Get latest version of reports so we are less likely to cause merge
        # conflicts.
        wr = vcs.get_working_repository()
        use_master = False
        if not need_checkin:
            url = os.path.join(
                wr.master_reporoot,
                sb.get_branch(),
                sb.get_top_component(),
                'report',
            ).replace('\\', '/')
            publish.create_branch(url, False)
            use_master = True
        wr.create_or_update_checkout(rr,
                                     sb.get_top_component(),
                                     'report',
                                     sb.get_branch(),
                                     None,
                                     use_master=use_master)
        need_checkin = vcs.folder_is_tied_to_vcs(rr)
        # Report our results.
        bi = buildinfo.BuildInfo()
        machineFolder = os.path.join(rr, bi.host).replace('\\', '/')
        summary = EvalSummary(sb.get_build_id(),
                              sb.get_sandboxtype().get_style(), bi.host,
                              state.phase, state.reason, state.start_time,
                              state.timestamps,
                              sb.get_targeted_platform_variant(), bi.os,
                              bi.bitness, bi.version)
        db = Dashboard(rr)
        db.add_summary(summary)
        if os.path.exists(os.path.join(root, 'eval-log.txt')):
            shutil.copy2(os.path.join(root, 'eval-log.txt'), machineFolder)
        # Check in our changes.
        if need_checkin:
            status = vcs.get_status(rr)
            if 'unknown' in status:
                vcs.add(rr)
            vcs.checkin(rr, msg="update dashboard", quiet_stderr=True)
            try:
                vcs.push(rr)
            except BzrCommandError, e:
                if 'diverged' in ("%s" % e):
                    print "\nAttemping to resolve diverged report aspect"
                    print "\nNuking report dir %s" % rr
                    if not ioutil.nuke(rr):
                        print "\nAuto resolving diverged report aspect failed!"

                    bi = BranchInfo(branchname=sb.get_branch(),
                                    componentname=sb.get_top_component(),
                                    aspectname='report')
                    aspectdir = bi.get_branchdir(wr.local_reporoot)
                    print "\nNuking report repo %s" % aspectdir
                    if not ioutil.nuke(aspectdir):
                        print "\nAuto resolving diverged report aspect failed!"

                    # Use the master because we have a problem here.
                    wr.create_local_branch(sb.get_top_component(),
                                           'report',
                                           sb.get_branch(),
                                           use_master=True)
                    wr.create_or_update_checkout(rr,
                                                 sb.get_top_component(),
                                                 'report',
                                                 sb.get_branch(),
                                                 None,
                                                 use_master=True)

                    db = Dashboard(rr)
                    db.add_summary(summary)
                    if os.path.exists(os.path.join(root, 'eval-log.txt')):
                        shutil.copy2(os.path.join(root, 'eval-log.txt'),
                                     machineFolder)

                    status = vcs.get_status(rr)
                    if 'unknown' in status:
                        vcs.add(rr)
                    vcs.checkin(rr, msg="update dashboard", quiet_stderr=True)
                    vcs.push(rr)
                    print "\nAuto resolve diverged report aspect success!"
                else:
                    raise e
    except:
        traceback.print_exc()
Example #11
0
def report(sb, state):
    rr = sb.get_report_root()
    root = sb.get_root()
    need_checkin = vcs.folder_is_tied_to_vcs(rr)
    try:
        # Get latest version of reports so we are less likely to cause merge
        # conflicts.
        wr = vcs.get_working_repository()
        use_master = False
        if not need_checkin:
            url = os.path.join(wr.master_reporoot, sb.get_branch(), sb.get_top_component(), 'report', ). replace('\\', '/')
            publish.create_branch(url, False)
            use_master = True
        wr.create_or_update_checkout(rr, sb.get_top_component(), 'report', sb.get_branch(), None, use_master=use_master)
        need_checkin = vcs.folder_is_tied_to_vcs(rr)
        # Report our results.
        bi = buildinfo.BuildInfo()
        machineFolder = os.path.join(rr, bi.host).replace('\\', '/')
        summary = EvalSummary(sb.get_build_id(), sb.get_sandboxtype().get_style(), bi.host,
                              state.phase, state.reason, state.start_time,
                              state.timestamps, sb.get_targeted_platform_variant(),
                              bi.os, bi.bitness, bi.version)
        db = Dashboard(rr)
        db.add_summary(summary)
        if os.path.exists(os.path.join(root, 'eval-log.txt')):
            shutil.copy2(os.path.join(root, 'eval-log.txt'), machineFolder)
        # Check in our changes.
        if need_checkin:
            status = vcs.get_status(rr)
            if 'unknown' in status:
                vcs.add(rr)
            vcs.checkin(rr, msg="update dashboard", quiet_stderr=True)
            try:
                vcs.push(rr)
            except BzrCommandError, e:
                if 'diverged' in ("%s" % e):
                    print "\nAttemping to resolve diverged report aspect"
                    print "\nNuking report dir %s" % rr
                    if not ioutil.nuke(rr):
                        print "\nAuto resolving diverged report aspect failed!"

                    bi = BranchInfo(branchname=sb.get_branch(), componentname=sb.get_top_component(), aspectname='report')
                    aspectdir = bi.get_branchdir(wr.local_reporoot)
                    print "\nNuking report repo %s" % aspectdir
                    if not ioutil.nuke(aspectdir):
                        print "\nAuto resolving diverged report aspect failed!"

                    # Use the master because we have a problem here.
                    wr.create_local_branch(sb.get_top_component(), 'report', sb.get_branch(), use_master=True)
                    wr.create_or_update_checkout(rr, sb.get_top_component(), 'report', sb.get_branch(), None, use_master=True)

                    db = Dashboard(rr)
                    db.add_summary(summary)
                    if os.path.exists(os.path.join(root, 'eval-log.txt')):
                        shutil.copy2(os.path.join(root, 'eval-log.txt'), machineFolder)

                    status = vcs.get_status(rr)
                    if 'unknown' in status:
                        vcs.add(rr)
                    vcs.checkin(rr, msg="update dashboard", quiet_stderr=True)
                    vcs.push(rr)
                    print "\nAuto resolve diverged report aspect success!"
                else:
                    raise e
    except:
        traceback.print_exc()
Example #12
0
def _get_deps(working_repo, platform, top_component, code_root, read_deps, already_analyzed, use_master=False, check_vcs=True):
    if top_component.name == 'buildscripts':
        top_component.reused_aspect = component.CODE_ASPECT_NAME

##TODO julie why would we do this?
##    if top_component.reused_aspect == component.BUILT_ASPECT_NAME:
##        interesting_branches = [b for b in working_repo.branches if b[1] == top_component.name and b[2].startswith(component.BUILT_ASPECT_NAME) and b[0] == top_component.branch]
##        if not interesting_branches:
##            top_component.reused_aspect = component.CODE_ASPECT_NAME
    folder = ''
    if (not top_component.revision) and code_root:
        fldr = os.path.join(code_root, top_component.name)
        if os.path.isdir(fldr):
            if check_vcs and vcs.folder_is_tied_to_vcs(fldr):
                output = vcs.get_status(fldr, status_filter=lambda lbl: lbl == 'modified' or lbl == 'added')
                if output:
                    if 'modified' in output:
                        if METADATA_FILE in output['modified']:
                            folder = fldr
                    if 'added' in output:
                        if METADATA_FILE in output['added']:
                            folder = fldr
            else:
                folder = fldr
    if folder:
        if folder in already_analyzed:
            return top_component #sections = already_analyzed[folder]
        else:
            print('\nLoading %s from %s.' % (METADATA_FILE, folder))
            x = get_section_info_from_disk(MISC_SECTION, folder)
            if 'terminal dependency' in x and top_component.reused_aspect.startswith(component.BUILT_ASPECT_NAME):
                return top_component
            sections = get_section_info_from_disk(DEPENDENCIES_SECTION, folder)
            already_analyzed[folder] = sections
    elif check_vcs:
        key = '%s:%s' % (top_component.name, top_component.reused_aspect) #str(top_component)
        if key in already_analyzed:
            return top_component #sections = already_analyzed[key]
        else:
            x = get_section_info_from_vcs(MISC_SECTION, top_component, working_repo, platform, use_master)
            if 'terminal dependency' in x and top_component.reused_aspect.startswith(component.BUILT_ASPECT_NAME):
                return top_component
            sections = get_section_info_from_vcs(DEPENDENCIES_SECTION, top_component, working_repo, platform, use_master)
            already_analyzed[key] = sections
    else:
        return top_component

    compOldDeps = False
    for componentname, info in sections.iteritems():
        componentname = componentname.strip()
        aspect, revision, old = component.parse_component_info(info)
        if aspect == component.BUILT_ASPECT_NAME:
            aspect += "." + platform
        if old:
            compOldDeps = True
        componentname, ignored, branch, task = working_repo.normalize(componentname, aspect, top_component.branch)
        if revision:
            m = _TAG_PAT.match(revision)
            if not m:
                raise Exception('%s is not a valid tag for pinning dependencies.' % revision)
        assert(aspect)
        top_component.dependencies.append(component.Component(componentname, branch, revision, aspect, parent=top_component))
    if compOldDeps:
        print('''Component %s/%s/%s has the old format for dependencies.
Please update dependencies in metadata.txt to match format found at:
https:// ... /working-with-code/concepts/dependencies''' % (top_component.name,top_component.reused_aspect,top_component.branch)) # TODO KIM refer to doc site
    top_component.rank += len(top_component.dependencies)
    for dep in top_component.dependencies:
        if top_component.reused_aspect.startswith(component.BUILT_ASPECT_NAME):
            dep.reused_aspect = top_component.reused_aspect
        # We are suspicious that this optimization isn't working
        if str(dep) not in read_deps or read_deps[str(dep)] != dep:
            read_deps[str(dep)] = dep
            dep = _get_deps(working_repo, platform, dep, code_root, read_deps, already_analyzed, use_master, check_vcs)
        top_component.rank += dep.rank
    return top_component
Example #13
0
def _get_deps(working_repo,
              platform,
              top_component,
              code_root,
              read_deps,
              already_analyzed,
              use_master=False,
              check_vcs=True):
    if top_component.name == 'buildscripts':
        top_component.reused_aspect = component.CODE_ASPECT_NAME


##TODO julie why would we do this?
##    if top_component.reused_aspect == component.BUILT_ASPECT_NAME:
##        interesting_branches = [b for b in working_repo.branches if b[1] == top_component.name and b[2].startswith(component.BUILT_ASPECT_NAME) and b[0] == top_component.branch]
##        if not interesting_branches:
##            top_component.reused_aspect = component.CODE_ASPECT_NAME
    folder = ''
    if (not top_component.revision) and code_root:
        fldr = os.path.join(code_root, top_component.name)
        if os.path.isdir(fldr):
            if check_vcs and vcs.folder_is_tied_to_vcs(fldr):
                output = vcs.get_status(fldr,
                                        status_filter=lambda lbl: lbl ==
                                        'modified' or lbl == 'added')
                if output:
                    if 'modified' in output:
                        if METADATA_FILE in output['modified']:
                            folder = fldr
                    if 'added' in output:
                        if METADATA_FILE in output['added']:
                            folder = fldr
            else:
                folder = fldr
    if folder:
        if folder in already_analyzed:
            return top_component  #sections = already_analyzed[folder]
        else:
            print('\nLoading %s from %s.' % (METADATA_FILE, folder))
            x = get_section_info_from_disk(MISC_SECTION, folder)
            if 'terminal dependency' in x and top_component.reused_aspect.startswith(
                    component.BUILT_ASPECT_NAME):
                return top_component
            sections = get_section_info_from_disk(DEPENDENCIES_SECTION, folder)
            already_analyzed[folder] = sections
    elif check_vcs:
        key = '%s:%s' % (top_component.name, top_component.reused_aspect
                         )  #str(top_component)
        if key in already_analyzed:
            return top_component  #sections = already_analyzed[key]
        else:
            x = get_section_info_from_vcs(MISC_SECTION, top_component,
                                          working_repo, platform, use_master)
            if 'terminal dependency' in x and top_component.reused_aspect.startswith(
                    component.BUILT_ASPECT_NAME):
                return top_component
            sections = get_section_info_from_vcs(DEPENDENCIES_SECTION,
                                                 top_component, working_repo,
                                                 platform, use_master)
            already_analyzed[key] = sections
    else:
        return top_component

    compOldDeps = False
    for componentname, info in sections.iteritems():
        componentname = componentname.strip()
        aspect, revision, old = component.parse_component_info(info)
        if aspect == component.BUILT_ASPECT_NAME:
            aspect += "." + platform
        if old:
            compOldDeps = True
        componentname, ignored, branch, task = working_repo.normalize(
            componentname, aspect, top_component.branch)
        if revision:
            m = _TAG_PAT.match(revision)
            if not m:
                raise Exception(
                    '%s is not a valid tag for pinning dependencies.' %
                    revision)
        assert (aspect)
        top_component.dependencies.append(
            component.Component(componentname,
                                branch,
                                revision,
                                aspect,
                                parent=top_component))
    if compOldDeps:
        print('''Component %s/%s/%s has the old format for dependencies.
Please update dependencies in metadata.txt to match format found at:
https:// ... /working-with-code/concepts/dependencies''' %
              (top_component.name, top_component.reused_aspect,
               top_component.branch))  # TODO KIM refer to doc site
    top_component.rank += len(top_component.dependencies)
    for dep in top_component.dependencies:
        if top_component.reused_aspect.startswith(component.BUILT_ASPECT_NAME):
            dep.reused_aspect = top_component.reused_aspect
        # We are suspicious that this optimization isn't working
        if str(dep) not in read_deps or read_deps[str(dep)] != dep:
            read_deps[str(dep)] = dep
            dep = _get_deps(working_repo, platform, dep, code_root, read_deps,
                            already_analyzed, use_master, check_vcs)
        top_component.rank += dep.rank
    return top_component