#!/usr/bin/python
#
# Run a build/test cycle and send out an email notification if the build
# goes from success to failure or vice versa
#
# Copyright (c) 2009-2021 Andreas Gustafsson.  All rights reserved.
# Please refer to the file COPYRIGHT for detailed copyright information.
#

from __future__ import print_function

import optparse

from bracket import *

from utils import adjacent_pairs

# Test the email notification code by printing the notification
# message for build break/fix number n (1 = most recent) on standard
# output.  The "success" argument is False for breaks, True for fixes.

def selftest(stage, n, success = False):
    use_current_repository()
    tag = stage + '_status'
    build_dates = [ts for ts in existing_build_dates_at_commits()
        if get_cached_status_if_any(ts, tag) is not None]

    breaks = [tsp for tsp in adjacent_pairs(build_dates)
        if status2bool(get_cached_status_if_any(tsp[0], tag)) == (not success) and \
           status2bool(get_cached_status_if_any(tsp[1], tag)) == success]

    chosen = breaks[-n]
    report_status_change(chosen[0], chosen[1], stage, mail = False, success = success)
    # Or to actually send mail and update the database:
    #maybe_report_build_status_change(chosen[1], success = success)

# Proposed but not yet implemented algorithm for choosing the
# commit to build and test:
#
# Let a "cgroup" mean a group of consecutive commits by the same
# committer (or, in the rare corner case where multiple people commit
# on the same second, by the same same set of committers).
#
# Our first choice is to test the last commit of the cgroup that
# includes the commit following the last one already built, so that we
# can attribute any new build breakage to a committer without
# getting bogged down by testing every commit in the cgroup.  Our
# second choice is to test the last safe commit.  To avoid falling too
# far behind, if there are more than N cgroups between the two,
# eliminate the first choice.

def choose_commit():
    return last_safe_commit_ts()

def notify(test_in_background):
    maybe_update_repo()
    ts = choose_commit()
    build_and_test(ts, test_in_background)

def notify_main(argv1):
    parser = optparse.OptionParser()
    parser.add_option("--test-in-background", action="store_true")
    add_bracket_options(parser)
    (options, args) = parser.parse_args(argv1)

    # If given arguments, run in test mode.  For example,
    #   bracket notify build 1
    # reports the most recent build failure on stdout, and
    #   bracket notify test_completed 2
    # reports the 2nd most recent failure to complete the ATF tests.
    if len(args) > 0:
        selftest(args[0], int(args[1]), False)
    else:
        notify(options.test_in_background)
