Provided by: libdebbugs-perl_2.6.0ubuntu1_all bug

NAME

       Debbugs::Control -- Routines for modifying the state of bugs

SYNOPSIS

       use Debbugs::Control;

DESCRIPTION

       This module is an abstraction of a lot of functions which originally were only present in
       service.in, but as time has gone on needed to be called from elsewhere.

       All of the public functions take the following options:

       debug -- scalar reference to which debbuging information is appended
       transcript -- scalar reference to which transcript information is appended
       affected_bugs -- hashref which is updated with bugs affected by this function

       Functions which should (probably) append to the .log file take the following options:

       requester -- Email address of the individual who requested the change
       request_addr -- Address to which the request was sent
       request_nn -- Name of queue file which caused this request
       request_msgid -- Message id of message which caused this request
       location -- Optional location; currently ignored but may be supported in the future for
       updating archived bugs upon archival
       message -- The original message which caused the action to be taken
       append_log -- Whether or not to append information to the log.

       append_log (for most functions) is a special option. When set to false, no appending to
       the log is done at all. When it is not present, the above information is faked, and
       appended to the log file. When it is true, the above options must be present, and their
       values are used.

GENERAL FUNCTIONS

   set_blocks
            eval {
                   set_block(bug          => $ref,
                             transcript   => $transcript,
                             ($dl > 0 ? (debug => $transcript):()),
                             requester    => $header{from},
                             request_addr => $controlrequestaddr,
                             message      => \@log,
                             affected_packages => \%affected_packages,
                             recipients   => \%recipients,
                             block        => [],
                            );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set blockers of $ref: $@";
               }

       Alters the set of bugs that block this bug from being fixed

       This requires altering both this bug (and those it's merged with) as well as the bugs that
       block this bug from being fixed (and those that it's merged with)

       block -- scalar or arrayref of blocking bugs to set, add or remove
       add -- if true, add blocking bugs
       remove -- if true, remove blocking bugs

   set_tag
            eval {
                   set_tag(bug          => $ref,
                           transcript   => $transcript,
                           ($dl > 0 ? (debug => $transcript):()),
                           requester    => $header{from},
                           request_addr => $controlrequestaddr,
                           message      => \@log,
                           affected_packages => \%affected_packages,
                           recipients   => \%recipients,
                           tag          => [],
                           add          => 1,
                          );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set tag on $ref: $@";
               }

       Sets, adds, or removes the specified tags on a bug

       tag -- scalar or arrayref of tags to set, add or remove
       add -- if true, add tags
       remove -- if true, remove tags
       warn_on_bad_tags -- if true (the default) warn if bad tags are passed.

   set_severity
            eval {
                   set_severity(bug          => $ref,
                                transcript   => $transcript,
                                ($dl > 0 ? (debug => $transcript):()),
                                requester    => $header{from},
                                request_addr => $controlrequestaddr,
                                message      => \@log,
                                affected_packages => \%affected_packages,
                                recipients   => \%recipients,
                                severity     => 'normal',
                               );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set the severity of bug $ref: $@";
               }

       Sets the severity of a bug. If severity is not passed, is undefined, or has zero length,
       sets the severity to the default severity.

   set_done
            eval {
                   set_done(bug          => $ref,
                            transcript   => $transcript,
                            ($dl > 0 ? (debug => $transcript):()),
                            requester    => $header{from},
                            request_addr => $controlrequestaddr,
                            message      => \@log,
                            affected_packages => \%affected_packages,
                            recipients   => \%recipients,
                           );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set foo $ref bar: $@";
               }

       Foo frobinates

   set_submitter
            eval {
                   set_submitter(bug          => $ref,
                                 transcript   => $transcript,
                                 ($dl > 0 ? (debug => $transcript):()),
                                 requester    => $header{from},
                                 request_addr => $controlrequestaddr,
                                 message      => \@log,
                                 affected_packages => \%affected_packages,
                                 recipients   => \%recipients,
                                 submitter    => $new_submitter,
                                 notify_submitter => 1,
                                 );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set the forwarded-to-address of $ref: $@";
               }

       Sets the submitter of a bug. If notify_submitter is true (the default), notifies the old
       submitter of a bug on changes

   set_forwarded
            eval {
                   set_forwarded(bug          => $ref,
                                 transcript   => $transcript,
                                 ($dl > 0 ? (debug => $transcript):()),
                                 requester    => $header{from},
                                 request_addr => $controlrequestaddr,
                                 message      => \@log,
                                 affected_packages => \%affected_packages,
                                 recipients   => \%recipients,
                                 forwarded    => $forward_to,
                                 );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set the forwarded-to-address of $ref: $@";
               }

       Sets the location to which a bug is forwarded. Given an undef forwarded, unsets forwarded.

   set_title
            eval {
                   set_title(bug          => $ref,
                             transcript   => $transcript,
                             ($dl > 0 ? (debug => $transcript):()),
                             requester    => $header{from},
                             request_addr => $controlrequestaddr,
                             message      => \@log,
                             affected_packages => \%affected_packages,
                             recipients   => \%recipients,
                             title        => $new_title,
                             );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set the title of $ref: $@";
               }

       Sets the title of a specific bug

   set_package
            eval {
                   set_package(bug          => $ref,
                               transcript   => $transcript,
                               ($dl > 0 ? (debug => $transcript):()),
                               requester    => $header{from},
                               request_addr => $controlrequestaddr,
                               message      => \@log,
                               affected_packages => \%affected_packages,
                               recipients   => \%recipients,
                               package      => $new_package,
                               is_source    => 0,
                              );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to assign or reassign $ref to a package: $@";
               }

       Indicates that a bug is in a particular package. If is_source is true, indicates that the
       package is a source package. [Internally, this causes src: to be prepended to the package
       name.]

       The default for is_source is 0. As a special case, if the package starts with 'src:', it
       is assumed to be a source package and is_source is overridden.

       The package option must match the package_name_re regex.

   set_found
            eval {
                   set_found(bug          => $ref,
                             transcript   => $transcript,
                             ($dl > 0 ? (debug => $transcript):()),
                             requester    => $header{from},
                             request_addr => $controlrequestaddr,
                             message      => \@log,
                             affected_packages => \%affected_packages,
                             recipients   => \%recipients,
                             found        => [],
                             add          => 1,
                            );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set found on $ref: $@";
               }

       Sets, adds, or removes the specified found versions of a package

       If the version list is empty, and the bug is currently not "done", causes the done field
       to be cleared.

       If any of the versions added to found are greater than any version in which the bug is
       fixed (or when the bug is found and there are no fixed versions) the done field is
       cleared.

   set_fixed
            eval {
                   set_fixed(bug          => $ref,
                             transcript   => $transcript,
                             ($dl > 0 ? (debug => $transcript):()),
                             requester    => $header{from},
                             request_addr => $controlrequestaddr,
                             message      => \@log,
                             affected_packages => \%affected_packages,
                             recipients   => \%recipients,
                             fixed        => [],
                             add          => 1,
                             reopen       => 0,
                            );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set fixed on $ref: $@";
               }

       Sets, adds, or removes the specified fixed versions of a package

       If the fixed versions are empty (or end up being empty after this call) or the greatest
       fixed version is less than the greatest found version and the reopen option is true, the
       bug is reopened.

       This function is also called by the reopen function, which causes all of the fixed
       versions to be cleared.

   set_merged
            eval {
                   set_merged(bug          => $ref,
                              transcript   => $transcript,
                              ($dl > 0 ? (debug => $transcript):()),
                              requester    => $header{from},
                              request_addr => $controlrequestaddr,
                              message      => \@log,
                              affected_packages => \%affected_packages,
                              recipients   => \%recipients,
                              merge_with   => 12345,
                              add          => 1,
                              force        => 1,
                              allow_reassign => 1,
                              reassign_same_source_only => 1,
                             );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to set merged on $ref: $@";
               }

       Sets, adds, or removes the specified merged bugs of a bug

       By default, requires

   affects
            eval {
                   affects(bug          => $ref,
                           transcript   => $transcript,
                           ($dl > 0 ? (debug => $transcript):()),
                           requester    => $header{from},
                           request_addr => $controlrequestaddr,
                           message      => \@log,
                           affected_packages => \%affected_packages,
                           recipients   => \%recipients,
                           packages     => undef,
                           add          => 1,
                           remove       => 0,
                          );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to mark $ref as affecting $packages: $@";
               }

       This marks a bug as affecting packages which the bug is not actually in. This should only
       be used in cases where fixing the bug instantly resolves the problem in the other
       packages.

       By default, the packages are set to the list of packages passed.  However, if you pass add
       => 1 or remove => 1, the list of packages passed are added or removed from the affects
       list, respectively.

SUMMARY FUNCTIONS

   summary
            eval {
                   summary(bug          => $ref,
                           transcript   => $transcript,
                           ($dl > 0 ? (debug => $transcript):()),
                           requester    => $header{from},
                           request_addr => $controlrequestaddr,
                           message      => \@log,
                           affected_packages => \%affected_packages,
                           recipients   => \%recipients,
                           summary      => undef,
                          );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to mark $ref with summary foo: $@";
               }

       Handles all setting of summary fields

       If summary is undef, unsets the summary

       If summary is 0 or -1, sets the summary to the first paragraph contained in the message
       passed.

       If summary is a positive integer, sets the summary to the message specified.

       Otherwise, sets summary to the value passed.

OUTLOOK FUNCTIONS

   outlook
            eval {
                   outlook(bug          => $ref,
                           transcript   => $transcript,
                           ($dl > 0 ? (debug => $transcript):()),
                           requester    => $header{from},
                           request_addr => $controlrequestaddr,
                           message      => \@log,
                           affected_packages => \%affected_packages,
                           recipients   => \%recipients,
                           outlook      => undef,
                          );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to mark $ref with outlook foo: $@";
               }

       Handles all setting of outlook fields

       If outlook is undef, unsets the outlook

       If outlook is 0, sets the outlook to the first paragraph contained in the message passed.

       If outlook is a positive integer, sets the outlook to the message specified.

       Otherwise, sets outlook to the value passed.

   clone_bug
            eval {
                   clone_bug(bug          => $ref,
                             transcript   => $transcript,
                             ($dl > 0 ? (debug => $transcript):()),
                             requester    => $header{from},
                             request_addr => $controlrequestaddr,
                             message      => \@log,
                             affected_packages => \%affected_packages,
                             recipients   => \%recipients,
                            );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to clone bug $ref bar: $@";
               }

       Clones the given bug.

       We currently don't support cloning merged bugs, but this could be handled by internally
       unmerging, cloning, then remerging the bugs.

OWNER FUNCTIONS

   owner
            eval {
                   owner(bug          => $ref,
                         transcript   => $transcript,
                         ($dl > 0 ? (debug => $transcript):()),
                         requester    => $header{from},
                         request_addr => $controlrequestaddr,
                         message      => \@log,
                         recipients   => \%recipients,
                         owner        => undef,
                        );
               };
               if ($@) {
                   $errors++;
                   print {$transcript} "Failed to mark $ref as having an owner: $@";
               }

       Handles all setting of the owner field; given an owner of undef or of no length, indicates
       that a bug is not owned by anyone.

ARCHIVE FUNCTIONS

   bug_archive
            my $error = '';
            eval {
               bug_archive(bug => $bug_num,
                           debug => \$debug,
                           transcript => \$transcript,
                          );
            };
            if ($@) {
               $errors++;
               transcript("Unable to archive $bug_num\n");
               warn $@;
            }
            transcript($transcript);

       This routine archives a bug

       bug -- bug number
       check_archiveable -- check wether a bug is archiveable before archiving; defaults to 1
       archive_unarchived -- whether to archive bugs which have not previously been archived;
       defaults to 1. [Set to 0 when used from control@]
       ignore_time -- whether to ignore time constraints when archiving a bug; defaults to 0.

   bug_unarchive
            my $error = '';
            eval {
               bug_unarchive(bug => $bug_num,
                             debug => \$debug,
                             transcript => \$transcript,
                            );
            };
            if ($@) {
               $errors++;
               transcript("Unable to archive bug: $bug_num");
            }
            transcript($transcript);

       This routine unarchives a bug

   append_action_to_log
            append_action_to_log

       This should probably be moved to Debbugs::Log; have to think that out some more.

PRIVATE FUNCTIONS

   __handle_affected_packages
            __handle_affected_packages(affected_packages => {},
                                       data => [@data],
                                      )

   __handle_debug_transcript
            my ($debug,$transcript) = __handle_debug_transcript(%param);

       Returns a debug and transcript filehandle

   __bug_info
            __bug_info($data)

       Produces a small bit of bug information to kick out to the transcript

   __internal_request
            __internal_request()
            __internal_request($level)

       Returns true if the caller of the function calling __internal_request belongs to
       __PACKAGE__

       This allows us to be magical, and don't bother to print bug info if the second caller is
       from this package, amongst other things.

       An optional level is allowed, which increments the number of levels to check by the given
       value. [This is basically for use by internal functions like __begin_control which are
       always called by "__PACKAGE__".

   __begin_control
            my %info = __begin_control(%param,
                                       archived=>1,
                                       command=>'unarchive');
            my ($debug,$transcript) = @info{qw(debug transcript)};
            my @data = @{$info{data}};
            my @bugs = @{$info{bugs}};

       Starts the process of modifying a bug; handles all of the generic things that almost every
       control request needs

       Returns a hash containing

       new_locks -- number of new locks taken out by this call
       debug -- the debug file handle
       transcript -- the transcript file handle
       data -- an arrayref containing the data of the bugs corresponding to this request
       bugs -- an arrayref containing the bug numbers of the bugs corresponding to this request

   __end_control
            __end_control(%info);

       Handles tearing down from a control request

   check_limit
            check_limit(data => \@data, limit => $param{limit});

       Checks to make sure that bugs match any limits; each entry of @data much satisfy the
       limit.

       Returns true if there are no entries in data, or there are no keys in limit; returns false
       (0) if there are any entries which do not match.

       The limit hashref elements can contain an arrayref of scalars to match; regexes are also
       acccepted. At least one of the entries in each element needs to match the corresponding
       field in all data for the limit to succeed.

   die
            sig_die "foo"

       We override die to specially handle unlocking files in the cases where we are called via
       eval. [If we're not called via eval, it doesn't matter.]