Example #1
0
def push_to_scm(dst_branch, push_map, if_not_exists=True, unless_hash=None):
    """Push commits to the specified remote branch

    :param str dst_branch:    The target remote branch to push changes into.
                              What this means in practice depends on the type
                              of remote SCM server being pushed to.
    :param str push_map:      The path to a file containing information about
                              remote SCM servers that is needed to push changes
                              to them.
    :param str if_not_exists: If set to 'True' (the default), check remote for
                              a similar patch before pushing, and don't push if
                              it exists.
    :param str unless_hash:   Given a Git hash value, or a commit ref, if HEAD
                              is equal to this commit, don't try to push it.
    """
    if unless_hash is not None:
        if get_patch_sha() == git_rev_parse(unless_hash):
            logger.info("HEAD commit is '%s', skipping push", unless_hash)
            return
    push_details = read_push_details(push_map)
    logger.info("Would push to: '%s'", push_details.push_url)
    if push_details.host_key:
        add_key_to_known_hosts(push_details.host_key)
    if if_not_exists and check_if_similar_patch_pushed(push_details):
        logger.info('Found similar patch in SCM server, not pushing')
        return
    dest_to_push_to = 'HEAD:refs/for/{0}'.format(dst_branch)
    logger.info("Push to: '%s' at '%s'", push_details.push_url,
                dest_to_push_to)
    git('push', push_details.push_url, dest_to_push_to)
Example #2
0
def push_to_scm(dst_branch, push_map, direct=False, if_not_exists=True, unless_hash=None):
    """Push commits to the specified remote branch

    :param str dst_branch:    The target remote branch to push changes into.
                              What this means in practice depends on the type
                              of remote SCM server being pushed to.
    :param str push_map:      The path to a file containing information about
                              remote SCM servers that is needed to push changes
                              to them.
    :param bool direct:       If set to True, bypass review and directly merge
                              the patch.
    :param str if_not_exists: If set to 'True' (the default), check remote for
                              a similar patch before pushing, and don't push if
                              it exists.
    :param str unless_hash:   Given a Git hash value, or a commit ref, if HEAD
                              is equal to this commit, don't try to push it.
    """
    if unless_hash is not None:
        if get_patch_sha() == git_rev_parse(unless_hash):
            logger.info("HEAD commit is '%s', skipping push", unless_hash)
            return
    push_details = read_push_details(push_map)
    logger.info("Would push to: '%s'", push_details.push_url)
    if push_details.host_key:
        add_key_to_known_hosts(push_details.host_key)
    if if_not_exists and check_if_similar_patch_pushed(push_details):
        logger.info('Found similar patch in SCM server, not pushing')
        return
    if direct:
        dest_to_push_to = 'HEAD:refs/heads/{0}'.format(dst_branch)
    else:
        dest_to_push_to = 'HEAD:refs/for/{0}'.format(dst_branch)
    logger.info("Push to: '%s' at '%s'", push_details.push_url, dest_to_push_to)
    git('push', push_details.push_url, dest_to_push_to)
Example #3
0
def update_branch(user: str, repo: str, sha: str, branch_name: str) -> None:
    git(["fetch", "origin", sha])
    git(["reset", "--hard", "FETCH_HEAD"])
    try:
        git(["branch", "-D", branch_name])
    except RuntimeError:
        # Ignore failures (i.e. the branch did not exist in the first place)
        pass
    git(["checkout", "-b", branch_name])

    # Create and push the branch
    git(["push", "origin", "--force", branch_name])
    print(f"Pushed branch {branch_name} with commit {sha}")
def main():
  """Mainline.

  Check for modified files in the index, try to determine whether or not
  they are text files, and then determine whether or not they are marked
  for keyword substitution.
  """
  for file in git( 'diff-index --cached --diff-filter=ACMRTUX ' + \
                   '--name-only HEAD' ).split('\n'):
    if( file ):
      mime = mimetypes.guess_type( file )
      if( (mime[0] is None or 'text' in mime[0]) and \
          ('true' == git('check-attr kwsub ' + file).split(': ')[2]) ):
        kwsub( file )
  sys.exit( 0 )
Example #5
0
def main():
    """Mainline.

  Check for modified files in the index, try to determine whether or not
  they are text files, and then determine whether or not they are marked
  for keyword substitution.
  """
    for file in git( 'diff-index --cached --diff-filter=ACMRTUX ' + \
                     '--name-only HEAD' ).split('\n'):
        if (file):
            mime = mimetypes.guess_type(file)
            if( (mime[0] is None or 'text' in mime[0]) and \
                ('true' == git('check-attr kwsub ' + file).split(': ')[2]) ):
                kwsub(file)
    sys.exit(0)
Example #6
0
def get_patch_header(header, default=None, commit='HEAD'):
    """Get the value of a given header in the given commit in $PWD

    :param str header:  The name of the header which value we want to get
    :param str default: A default value to return if the give header is not
                        found. If this is not set, an KeyError exception will
                        be thrown instead of returning a value.
    :param str commit:  (Optional) The commit to look for headers in. Defaults
                        to HEAD.

    :rtype: str
    :returns: The value of the given header if specified in the commit message
              of the HEAD commit in $CWD
    """
    try:
        msg_lines = git('log', '-1', '--pretty=format:%b', commit).splitlines()
    except GitProcessError:
        raise KeyError("Commit ref '{0}' not found".format(commit))
    header_value = next(
        (line[len(header) + 2:]
         for line in msg_lines if line.startswith(header + ': ')), None)
    if header_value is None:
        if default is None:
            raise KeyError("Header: '{0}' not found in ref: '{1}'".format(
                header, commit))
        else:
            return default
    return header_value
Example #7
0
def get_patch_header(header, default=None, commit='HEAD'):
    """Get the value of a given header in the given commit in $PWD

    :param str header:  The name of the header which value we want to get
    :param str default: A default value to return if the give header is not
                        found. If this is not set, an KeyError exception will
                        be thrown instead of returning a value.
    :param str commit:  (Optional) The commit to look for headers in. Defaults
                        to HEAD.

    :rtype: str
    :returns: The value of the given header if specified in the commit message
              of the HEAD commit in $CWD
    """
    try:
        msg_lines = git('log', '-1', '--pretty=format:%b', commit).splitlines()
    except GitProcessError:
        raise KeyError("Commit ref '{0}' not found".format(commit))
    header_value = next((
        line[len(header) + 2:] for line in msg_lines
        if line.startswith(header + ': ')
    ), None)
    if header_value is None:
        if default is None:
            raise KeyError(
                "Header: '{0}' not found in ref: '{1}'".format(header, commit)
            )
        else:
            return default
    return header_value
Example #8
0
def main():
  """Mainline.

  Check for modified files in the index, try to determine whether or not
  they are text files, and then determine whether or not they are marked
  for keyword substitution.
  """
  gcmd = 'diff-index --cached --diff-filter=ACMRTUX --name-only HEAD'
  for fname in [ fnam for fnam in git( gcmd ).split('\n') if fnam ]:
    # Try to determine the mime type of the file.
    mime = mimetypes.guess_type( fname )
    if( (mime[0] is None) or ('text' in mime[0]) ):
      # Good chance it's a text file.  See if we're allowed to work on it.
      if( 'true' == git( 'check-attr kwsub ' + fname ).split(': ')[2] ):
        # Perform keyword substitution.
        kwsub( fname )
  sys.exit( 0 )
Example #9
0
    def check_pr_title():
        remote = git(["config", "--get", f"remote.{args.remote}.url"])
        user, repo = parse_remote(remote)

        if args.pr_title:
            title = args.pr_title
        else:
            github = GitHubRepo(token=os.environ["TOKEN"],
                                user=user,
                                repo=repo)
            pr = github.get(f"pulls/{args.pr}")
            title = pr["title"]
        print("pr title:", title)
        return title.startswith("[skip ci]")
Example #10
0
    def check_pr_title():
        remote = git(["config", "--get", f"remote.{args.remote}.url"])
        user, repo = parse_remote(remote)

        if args.pr_title:
            title = args.pr_title
        else:
            github = GitHubRepo(token=os.environ["TOKEN"],
                                user=user,
                                repo=repo)
            pr = github.get(f"pulls/{args.pr}")
            title = pr["title"]
        logging.info(f"pr title: {title}")
        tags = tags_from_title(title)
        logging.info(f"Found title tags: {tags}")
        return "skip ci" in tags
Example #11
0
def get_remote_url_from_ws():
    """
    Get git 'origin' remote url from $CWD using 'git remote' command

    :rtype: string
    :returns: The 'origin' remote url
    """
    remotes_lines = git('remote', '-v').splitlines()
    remotes_name_data = (l.split(None, 1) for l in remotes_lines)
    remotes = ([n] + d.rsplit(' ', 1) for n, d in remotes_name_data)
    try:
        return next(url for name, url, role in remotes
                    if name == 'origin' and role == '(push)')
    except StopIteration:
        raise ValueError(
            'No appropriate Git remote url defined in current directory')
Example #12
0
def get_remote_url_from_ws():
    """
    Get git 'origin' remote url from $CWD using 'git remote' command

    :rtype: string
    :returns: The 'origin' remote url
    """
    remotes_lines = git('remote', '-v').splitlines()
    remotes_name_data = (l.split(None, 1) for l in remotes_lines)
    remotes = ([n] + d.rsplit(' ', 1) for n, d in remotes_name_data)
    try:
        return next(
            url for name, url, role in remotes
            if name == 'origin' and role == '(push)'
        )
    except StopIteration:
        raise ValueError(
            'No appropriate Git remote url defined in current directory'
        )
Example #13
0
def do_command(repo, queue):
    """
    Execute the command in the given repository.
    """
    try:
        chdir(repo)
        command = git(argv[1:])
        if len(command) > 0:
            # Empty string prevents printing the tuple in python2
            output = ''
            output += '\n'
            output += 'in repo {}:\n'.format(repo)
            for line in command:
                output += '{}\n'.format(wrap(line))
            queue.put(output)

    except ErrorReturnCode as ex:
        error = ''
        error += "in repo {}:".format(repo)
        error += wrap('Command: "{}" failed!\n'.format(ex.full_cmd))
        queue.put(error)
Example #14
0
def do_command(repo, queue):
    """
    Execute the command in the given repository.
    """
    try:
        chdir(repo)
        command = git(argv[1:])
        if len(command) > 0:
            # Empty string prevents printing the tuple in python2
            output = ''
            output += '\n'
            output += 'in repo {}:\n'.format(repo)
            for line in command:
                output += '{}\n'.format(wrap(line))
            queue.put(output)

    except ErrorReturnCode as ex:
        error = ''
        error += "in repo {}:".format(repo)
        error += wrap('Command: "{}" failed!\n'.format(ex.full_cmd))
        queue.put(error)
Example #15
0
    return textwrap.indent(long_str, "    ")


if __name__ == "__main__":
    help = "Exits with 1 if CI should run slow tests, 0 otherwise"
    parser = argparse.ArgumentParser(description=help)
    parser.add_argument("--pr", required=True)
    parser.add_argument("--remote",
                        default="origin",
                        help="ssh remote to parse")
    parser.add_argument(
        "--pr-body",
        help="(testing) PR body to use instead of fetching from GitHub")
    args = parser.parse_args()

    branch = git(["rev-parse", "--abbrev-ref", "HEAD"])

    # Don't skip slow tests on main or ci-docker-staging
    skip_branches = {"main", "ci-docker-staging"}
    if branch in skip_branches:
        print(f"Branch {branch} is in {skip_branches}, running slow tests")
        exit(1)
    print(
        f"Branch {branch} is not in {skip_branches}, checking last commit...")

    if args.pr_body:
        body = args.pr_body
    else:
        remote = git(["config", "--get", f"remote.{args.remote}.url"])
        user, repo = parse_remote(remote)
Example #16
0
from git_utils import git, GitHubRepo, parse_remote

if __name__ == "__main__":
    help = "Exits with 0 if CI should be skipped, 1 otherwise"
    parser = argparse.ArgumentParser(description=help)
    parser.add_argument("--pr", required=True)
    parser.add_argument("--remote",
                        default="origin",
                        help="ssh remote to parse")
    parser.add_argument(
        "--pr-title",
        help="(testing) PR title to use instead of fetching from GitHub")
    args = parser.parse_args()

    branch = git(["rev-parse", "--abbrev-ref", "HEAD"])
    log = git(["log", "--format=%s", "-1"])

    # Check the PR's title (don't check this until everything else passes first)
    def check_pr_title():
        remote = git(["config", "--get", f"remote.{args.remote}.url"])
        user, repo = parse_remote(remote)

        if args.pr_title:
            title = args.pr_title
        else:
            github = GitHubRepo(token=os.environ["TOKEN"],
                                user=user,
                                repo=repo)
            pr = github.get(f"pulls/{args.pr}")
            title = pr["title"]
Example #17
0
    parser.add_argument("--cutoff-pr-number",
                        default=0,
                        type=int,
                        help="ssh remote to parse")
    parser.add_argument("--dry-run",
                        action="store_true",
                        help="don't update GitHub")
    parser.add_argument("--allowlist", help="filter by these PR authors")
    parser.add_argument(
        "--pr-json",
        help="(testing) data for testing to use instead of GitHub")
    parser.add_argument("--now",
                        help="(testing) custom string for current time")
    args = parser.parse_args()

    remote = git(["config", "--get", f"remote.{args.remote}.url"])
    user, repo = parse_remote(remote)

    wait_time = datetime.timedelta(minutes=int(args.wait_time_minutes))
    cutoff_pr_number = int(args.cutoff_pr_number)
    print(
        "Running with:\n"
        f"  time cutoff: {wait_time}\n"
        f"  number cutoff: {cutoff_pr_number}\n"
        f"  dry run: {args.dry_run}\n"
        f"  user/repo: {user}/{repo}\n",
        end="",
    )

    # [slow rollout]
    # This code is here to gate this feature to a limited set of people before
Example #18
0
def kwsub(filepath):
    """Scan through the given file line-by-line looking for matching keywords.
  Substitute appropriate values if keywords are found.

  filepath  - Path to the file to be scanned.
  """
    tmppath = filepath + '.tmp'
    # Try to open files. rfile is the reading file, wfile is the temp writing
    # file. If this fails, abort commit.
    try:
        rfile = open(filepath, 'r')
        wfile = open(tmppath, 'w')
        # Copy over stat modes (rwx) from the original file. Important for scripts!
        os.chmod(tmppath, os.stat(filepath).st_mode)
    except Exception as e:
        os.remove(tmppath)
        sys.exit(e)

    # Gather system information.
    user = getuser()
    git_user = git_config('user.name')
    git_email = git_config('user.email')
    fqdn = getfqdn()
    an = getenv('GIT_AUTHOR_NAME') or git_user or user
    ae = getenv('GIT_AUTHOR_EMAIL') or git_email or (user + '@' + fqdn)
    cn = getenv('GIT_COMMITTER_NAME') or git_user or user
    ce = getenv('GIT_COMMITTER_EMAIL') or git_email or (user + '@' + fqdn)
    author = an + ' <' + ae + '>'
    committer = cn + ' <' + ce + '>'
    dt = datetime.now().replace(tzinfo=LocalTZ)
    dfmt = '%Y-%m-%d %H:%M:%S'
    ad = git_parse_date(getenv('GIT_AUTHOR_DATE')) or dt
    adate = ad.strftime(dfmt + ' %z')
    cd = git_parse_date(getenv('GIT_COMMITTER_DATE')) or dt
    cdate = cd.strftime(dfmt + ' %z')
    name = os.path.basename(filepath)

    # Set the keywords and their substitutions.
    kw = {
        'Name': 'Name: ' + name,
        'Copyright': 'Copyright (C) ' + str(ad.year) + ' ' + author,
        'Date': 'Date: ' + cdate,
        'Id': 'Id: ' + name + '; ' + cdate + '; ' + cn,
        'Author': 'Author: ' + author,
        'AName': 'AName: ' + an,
        'AEmail': 'AEmail: ' + ae,
        'ADate': 'ADate: ' + adate,
        'Committer': 'Committer: ' + committer,
        'CName': 'CName: ' + cn,
        'CEmail': 'CEmail: ' + ce,
        'CDate': 'CDate: ' + cdate,
    }

    # Begin substitution.
    subbed = False
    for line in rfile:
        for key in kw:
            for m in re.finditer(r'\$(' + key + ')([^$]*)\$', line):
                line = line[:m.start()] + '$' + kw[key] + '$' + line[m.end():]
                subbed = True
                # Debug line.
                #print filepath + ': ' + line
        wfile.write(line)

    rfile.close()
    wfile.close()

    if (subbed):
        os.remove(filepath)
        os.rename(tmppath, filepath)
        git('add ' + filepath)
    else:
        os.remove(tmppath)

    # Set environment variables so git metadata matches in-file metadata.
    os.environ['GIT_AUTHOR_NAME'] = an
    os.environ['GIT_AUTHOR_EMAIL'] = ae
    os.environ['GIT_AUTHOR_DATE'] = ad.strftime(dfmt)
    os.environ['GIT_COMMITTER_NAME'] = cn
    os.environ['GIT_COMMITTER_EMAIL'] = ce
    os.environ['GIT_COMMITTER_DATE'] = cd.strftime(dfmt)

    # Done.
    return
Example #19
0
def get_patch_sha():
    """Get the hash of HEAD in $PWD

    :rtype: str
    """
    return git('log', '-1', '--pretty=format:%H')
Example #20
0
def get_patch_sha():
    """Get the hash of HEAD in $PWD

    :rtype: str
    """
    return git('log', '-1', '--pretty=format:%H')
Example #21
0
def kwsub( filepath ):
  """Perform keyword substitution on the given file.

  filepath  - The pathname of the file to be operated upon.

  Notes:  This function scans through the given file line-by-line
          looking for keywords.  It then expands those keywords by
          adding or replacing the associated value string.  The changes,
          if any, are written to a temporary file.  If the process
          completes successfully, the temporary file replaces the
          original and 'git add' is called to add the updated version to
          the repositiory.

          If there is an error opening either the source or temporary
          file used by this function, sys.exit() will be called, which
          will abort the commit that caused this pre-commit hook script
          to be called.
  """
  # FIX:  Creating a temporary file by simply adding '.tmp' to the pathname
  #       could (in theory) lead to overwriting of some existing file that
  #       the user actually wanted.  It'd be better to use something like
  #       mkstemp(3).  Fortunately, Python has such magic:
  #         https://docs.python.org/2/library/tempfile.html
  #
  #     - It would be nice if this function could be run stand-alone, so
  #       that it could be used in more situations than just a pre-commit
  #       script.  It does nice stuff.
  #       Suggestion:  Move the calls to sys.exit() and 'git add' out of the
  #       function and let the function return true/false or some other
  #       status indication.  On success, do the 'git add'.  On failure
  #       exit the program.
  #
  #     - Delete this FIX block.  ;)
  # /FIX

  # Try to open files.
  #   rfile is the file to be read (source file)
  #   wfile is the temporary file that will be written
  # If opening the files or copying permissions fails, then bail out.
  tmppath = filepath + '.tmp'
  try:
    rfile = open( filepath, 'r' )
    wfile = open( tmppath,  'w' )
    # Copy over stat modes (rwx) from the original file.  Important for scripts!
    os.chmod( tmppath, os.stat( filepath ).st_mode )
  except Exception as e:
    os.remove( tmppath )
    sys.exit( e )

  # Gather system information.
  user      = getuser()
  git_user  = git_config( 'user.name' )
  git_email = git_config( 'user.email' )
  fqdn      = getfqdn()
  an = getenv('GIT_AUTHOR_NAME') or git_user or user
  ae = getenv('GIT_AUTHOR_EMAIL') or git_email or (user + '@' + fqdn)
  cn = getenv('GIT_COMMITTER_NAME') or git_user or user
  ce = getenv('GIT_COMMITTER_EMAIL') or git_email or (user + '@' + fqdn)
  author = an + ' <' + ae + '>'
  committer = cn + ' <' + ce + '>'
  dt = datetime.now().replace( tzinfo=LocalTZ )
  dfmt = '%Y-%m-%d %H:%M:%S'
  ad = git_parse_date( getenv( 'GIT_AUTHOR_DATE' ) ) or dt
  adate = ad.strftime( dfmt + ' %z' )
  cd = git_parse_date( getenv( 'GIT_COMMITTER_DATE' ) ) or dt
  cdate = cd.strftime( dfmt + ' %z' )
  name = os.path.basename( filepath )

  # Set the keywords and their substitutions.
  kw = { 'Name'     : 'Name: ' + name,
         'Copyright': 'Copyright (C) ' + str(ad.year) + ' ' + author,
         'Date'     : 'Date: ' + cdate,
         'Id'       : 'Id: ' + name + '; ' + cdate + '; ' + cn,
         'Author'   : 'Author: ' + author,
         'AName'    : 'AName: ' + an,
         'AEmail'   : 'AEmail: ' + ae,
         'ADate'    : 'ADate: ' + adate,
         'Committer': 'Committer: ' + committer,
         'CName'    : 'CName: ' + cn,
         'CEmail'   : 'CEmail: ' + ce,
         'CDate'    : 'CDate: ' + cdate,
       }

  # Begin substitution.
  subbed = False
  for line in rfile:
    if '$' in line:
      for key in kw:
        for m in re.finditer( r'\$(' + key + ')([^$]*)\$', line ):
          line = line[:m.start()] + '$' + kw[key] + '$' + line[m.end():]
          subbed = True
          # DEBUG: print filepath + ': ' + line
    wfile.write( line )

  # Close 'em.
  rfile.close()
  wfile.close()

  # Update the files.
  if( subbed ):
    # Replace the original file with the new one.
    os.remove( filepath )
    os.rename( tmppath, filepath )
    git( 'add ' + filepath )
  else:
    # ...or just remove the tmpfile if no changes were made.
    os.remove( tmppath )

  # Set environment variables so that git metadata matches in-file metadata.
  os.environ[ 'GIT_AUTHOR_NAME'     ] = an
  os.environ[ 'GIT_AUTHOR_EMAIL'    ] = ae
  os.environ[ 'GIT_AUTHOR_DATE'     ] = ad.strftime( dfmt )
  os.environ[ 'GIT_COMMITTER_NAME'  ] = cn
  os.environ[ 'GIT_COMMITTER_EMAIL' ] = ce
  os.environ[ 'GIT_COMMITTER_DATE'  ] = cd.strftime( dfmt )

  # Done.
  return
Example #22
0
    parser.add_argument("--remote",
                        default="origin",
                        help="ssh remote to parse")
    parser.add_argument("--dry-run",
                        action="store_true",
                        help="don't send PR to GitHub")
    parser.add_argument("--testing-docker-data",
                        help="JSON data to mock Docker Hub API response")
    args = parser.parse_args()

    # Install test mock if necessary
    if args.testing_docker_data is not None:
        docker_api = _testing_docker_api(
            data=json.loads(args.testing_docker_data))

    remote = git(["config", "--get", f"remote.{args.remote}.url"])
    user, repo = parse_remote(remote)

    # Read the existing images from the Jenkinsfile
    logging.info(f"Reading {JENKINSFILE}")
    with open(JENKINSFILE) as f:
        content = f.readlines()

    # Build a new Jenkinsfile with the latest images from tlcpack or tlcpackstaging
    new_content = []
    replacements = {}
    for line in content:
        m = re.match(r"^(ci_[a-zA-Z0-9]+) = \'(.*)\'", line.strip())
        if m is not None:
            logging.info(f"Found match on line {line.strip()}")
            groups = m.groups()
Example #23
0
def display(long_str: str) -> str:
    return textwrap.indent(long_str, "    ")


if __name__ == "__main__":
    help = "Exits with 1 if CI should run slow tests, 0 otherwise"
    parser = argparse.ArgumentParser(description=help)
    parser.add_argument("--pr", required=True)
    parser.add_argument("--remote", default="origin", help="ssh remote to parse")
    parser.add_argument(
        "--pr-body", help="(testing) PR body to use instead of fetching from GitHub"
    )
    args = parser.parse_args()

    branch = git(["rev-parse", "--abbrev-ref", "HEAD"])

    # Don't skip slow tests on main or ci-docker-staging
    skip_branches = {"main", "ci-docker-staging"}
    if branch in skip_branches:
        print(f"Branch {branch} is in {skip_branches}, running slow tests")
        exit(1)
    print(f"Branch {branch} is not in {skip_branches}, checking last commit...")

    log = git(["log", "--format=%B", "-1"])

    # Check if anything in the last commit's body message matches
    log_match, reason = check_match(log, SLOW_TEST_TRIGGERS)
    if log_match:
        print(f"Matched {reason} in commit message:\n{display(log)}, running slow tests")
        exit(1)
Example #24
0
            return glob
    return None


if __name__ == "__main__":
    help = "Exits with code 1 if a change only touched files, indicating that CI could be skipped for this changeset"
    parser = argparse.ArgumentParser(description=help)
    parser.add_argument(
        "--files",
        help="(testing only) comma separated list of files to check")
    args = parser.parse_args()
    print(args)
    if args.files is not None:
        diff = [x for x in args.files.split(",") if x.strip() != ""]
    else:
        diff = git(
            ["diff", "--no-commit-id", "--name-only", "-r", "origin/main"])
        diff = diff.split("\n")
        diff = [d.strip() for d in diff]
        diff = [d for d in diff if d != ""]

    print(f"Changed files:\n{diff}")

    if len(diff) == 0:
        print("Found no changed files, skipping CI")
        exit(0)

    print(f"Checking with globs:\n{globs}")

    for file in diff:
        match = match_any(file)
        if match is None:
Example #25
0
def kwsub( filepath ):
  """Scan through the given file line-by-line looking for matching keywords.
  Substitute appropriate values if keywords are found.

  filepath  - Path to the file to be scanned.
  """
  tmppath = filepath + '.tmp'
  # Try to open files. rfile is the reading file, wfile is the temp writing
  # file. If this fails, abort commit.
  try:
    rfile = open( filepath, 'r' )
    wfile = open( tmppath, 'w' )
    # Copy over stat modes (rwx) from the original file. Important for scripts!
    os.chmod( tmppath, os.stat( filepath ).st_mode )
  except Exception as e:
    os.remove( tmppath )
    sys.exit( e )

  # Gather system information.
  user      = getuser()
  git_user  = git_config( 'user.name' )
  git_email = git_config( 'user.email' )
  fqdn      = getfqdn()
  an = getenv('GIT_AUTHOR_NAME') or git_user or user
  ae = getenv('GIT_AUTHOR_EMAIL') or git_email or (user + '@' + fqdn)
  cn = getenv('GIT_COMMITTER_NAME') or git_user or user
  ce = getenv('GIT_COMMITTER_EMAIL') or git_email or (user + '@' + fqdn)
  author = an + ' <' + ae + '>'
  committer = cn + ' <' + ce + '>'
  dt = datetime.now().replace( tzinfo=LocalTZ )
  dfmt = '%Y-%m-%d %H:%M:%S'
  ad = git_parse_date( getenv( 'GIT_AUTHOR_DATE' ) ) or dt
  adate = ad.strftime( dfmt + ' %z' )
  cd = git_parse_date( getenv( 'GIT_COMMITTER_DATE' ) ) or dt
  cdate = cd.strftime( dfmt + ' %z' )
  name = os.path.basename( filepath )

  # Set the keywords and their substitutions.
  kw = { 'Name'     : 'Name: ' + name,
         'Copyright': 'Copyright (C) ' + str(ad.year) + ' ' + author,
         'Date'     : 'Date: ' + cdate,
         'Id'       : 'Id: ' + name + '; ' + cdate + '; ' + cn,
         'Author'   : 'Author: ' + author,
         'AName'    : 'AName: ' + an,
         'AEmail'   : 'AEmail: ' + ae,
         'ADate'    : 'ADate: ' + adate,
         'Committer': 'Committer: ' + committer,
         'CName'    : 'CName: ' + cn,
         'CEmail'   : 'CEmail: ' + ce,
         'CDate'    : 'CDate: ' + cdate,
       }

  # Begin substitution.
  subbed = False
  for line in rfile:
    for key in kw:
      for m in re.finditer( r'\$(' + key + ')([^$]*)\$', line ):
        line = line[:m.start()] + '$' + kw[key] + '$' + line[m.end():]
        subbed = True
        # Debug line.
        #print filepath + ': ' + line
    wfile.write( line )

  rfile.close()
  wfile.close()

  if( subbed ):
    os.remove( filepath )
    os.rename( tmppath, filepath )
    git( 'add ' + filepath )
  else:
    os.remove( tmppath )

  # Set environment variables so git metadata matches in-file metadata.
  os.environ[ 'GIT_AUTHOR_NAME' ]  = an
  os.environ[ 'GIT_AUTHOR_EMAIL' ] = ae
  os.environ[ 'GIT_AUTHOR_DATE' ]  = ad.strftime( dfmt )
  os.environ[ 'GIT_COMMITTER_NAME' ]  = cn
  os.environ[ 'GIT_COMMITTER_EMAIL' ] = ce
  os.environ[ 'GIT_COMMITTER_DATE' ]  = cd.strftime( dfmt )

  # Done.
  return
Example #26
0
    travis_event_type = os.environ["TRAVIS_EVENT_TYPE"]
    travis_build_stage = os.environ["TRAVIS_BUILD_STAGE_NAME"]

    try:
        # If it's not an sbt task, we always run it no matter what.
        task = os.environ["TASK"]
    except KeyError:
        sbt_project_name = os.environ["SBT_PROJECT"]

        repo = Repository(".sbt_metadata")

        if travis_event_type == "pull_request":
            changed_paths = get_changed_paths("HEAD", "master")
        else:
            git("fetch", "origin")
            changed_paths = get_changed_paths(os.environ["TRAVIS_COMMIT_RANGE"])

        if should_run_sbt_project(repo, sbt_project_name, changed_paths=changed_paths):
            task = "%s-test" % sbt_project_name
        else:
            print(
                "Nothing in this patch affects %s, so skipping tests" % sbt_project_name
            )
            sys.exit(0)

    make(task)

    if travis_event_type == "push" and travis_build_stage == "Services":
        make(task.replace("test", "publish"))