]>
git.ipfire.org Git - thirdparty/gcc.git/blob - maintainer-scripts/branch_changer.py
3 # The script requires simplejson, requests, semantic_version packages, in case
5 # zypper in python3-simplejson python3-requests
6 # pip3 install semantic_version
13 from semantic_version
import Version
15 base_url
= 'https://gcc.gnu.org/bugzilla/rest.cgi/'
16 statuses
= [ 'UNCONFIRMED' , 'ASSIGNED' , 'SUSPENDED' , 'NEW' , 'WAITING' , 'REOPENED' ]
17 search_summary
= ' Regression]'
18 regex
= '(.*\[)([0-9\./]*)( [rR]egression])(.*)'
21 def __init__ ( self
, data
):
24 self
. fail_versions
= []
25 self
. is_regression
= False
28 self
. parse_known_to_fail ()
30 def parse_summary ( self
):
31 m
= re
. match ( regex
, self
. data
[ 'summary' ])
33 self
. versions
= m
. group ( 2 ). split ( '/' )
34 self
. is_regression
= True
37 def parse_known_to_fail ( self
):
38 v
= self
. data
[ 'cf_known_to_fail' ]. strip ()
40 self
. fail_versions
= [ x
for x
in re
. split ( ' |,' , v
) if x
!= '' ]
43 return 'PR %d ( %s )' % ( self
. data
[ 'id' ], self
. data
[ 'summary' ])
45 def remove_release ( self
, release
):
46 # Do not remove last value of [x Regression]
47 if len ( self
. versions
) == 1 :
49 self
. versions
= list ( filter ( lambda x
: x
!= release
, self
. versions
))
51 def add_release ( self
, releases
):
52 parts
= releases
. split ( ':' )
53 assert len ( parts
) == 2
54 for i
, v
in enumerate ( self
. versions
):
56 self
. versions
. insert ( i
+ 1 , parts
[ 1 ])
59 def add_known_to_fail ( self
, release
):
60 if release
in self
. fail_versions
:
63 self
. fail_versions
. append ( release
)
66 def update_summary ( self
, api_key
, doit
):
67 summary
= self
. data
[ 'summary' ]
68 new_summary
= self
. serialize_summary ()
69 if new_summary
!= summary
:
71 print ( ' changing summary: " %s " to " %s "' % ( summary
, new_summary
))
72 self
. modify_bug ( api_key
, { 'summary' : new_summary
}, doit
)
78 def change_milestone ( self
, api_key
, old_milestone
, new_milestone
, comment
, new_fail_version
, doit
):
79 old_major
= Bug
. get_major_version ( old_milestone
)
80 new_major
= Bug
. get_major_version ( new_milestone
)
84 if old_major
== new_major
:
85 args
[ 'target_milestone' ] = new_milestone
86 print ( ' changing target milestone: " %s " to " %s " (same branch)' % ( old_milestone
, new_milestone
))
87 elif self
. is_regression
and new_major
in self
. versions
:
88 args
[ 'target_milestone' ] = new_milestone
89 print ( ' changing target milestone: " %s " to " %s " (regresses with the new milestone)' % ( old_milestone
, new_milestone
))
91 print ( ' not changing target milestone: not a regression or does not regress with the new milestone' )
93 if 'target_milestone' in args
and comment
!= None :
94 print ( ' adding comment: " %s "' % comment
)
95 args
[ 'comment' ] = { 'comment' : comment
}
97 if new_fail_version
!= None :
98 if self
. add_known_to_fail ( new_fail_version
):
99 s
= self
. serialize_known_to_fail ()
100 print ( ' changing known_to_fail: " %s " to " %s "' % ( self
. data
[ 'cf_known_to_fail' ], s
))
101 args
[ 'cf_known_to_fail' ] = s
103 if len ( args
. keys ()) != 0 :
104 self
. modify_bug ( api_key
, args
, doit
)
109 def serialize_summary ( self
):
110 assert self
. versions
!= None
111 assert self
. is_regression
== True
113 new_version
= '/' . join ( self
. versions
)
114 new_summary
= self
. regex_match
. group ( 1 ) + new_version
+ self
. regex_match
. group ( 3 ) + self
. regex_match
. group ( 4 )
117 def serialize_known_to_fail ( self
):
118 assert type ( self
. fail_versions
) is list
119 return ', ' . join ( sorted ( self
. fail_versions
, key
= lambda x
: Version ( x
, partial
= True )))
121 def modify_bug ( self
, api_key
, params
, doit
):
122 u
= base_url
+ 'bug/' + str ( self
. data
[ 'id' ])
125 'ids' : [ self
. data
[ 'id' ]],
131 r
= requests
. put ( u
, data
= json
. dumps ( data
), headers
= { "content-type" : "text/javascript" })
135 def get_major_version ( release
):
136 parts
= release
. split ( '.' )
137 assert len ( parts
) == 2 or len ( parts
) == 3
138 return '.' . join ( parts
[:- 1 ])
141 def get_bugs ( api_key
, query
):
143 r
= requests
. get ( u
, params
= query
)
144 return [ Bug ( x
) for x
in r
. json ()[ 'bugs' ]]
146 def search ( api_key
, remove
, add
, limit
, doit
):
147 bugs
= Bug
. get_bugs ( api_key
, { 'api_key' : api_key
, 'summary' : search_summary
, 'bug_status' : statuses
})
148 bugs
= list ( filter ( lambda x
: x
. is_regression
, bugs
))
153 bug
. remove_release ( remove
)
157 if bug
. update_summary ( api_key
, doit
):
159 if modified
== limit
:
162 print ( ' \n Modified PRs: %d ' % modified
)
164 def replace_milestone ( api_key
, limit
, old_milestone
, new_milestone
, comment
, add_known_to_fail
, doit
):
165 bugs
= Bug
. get_bugs ( api_key
, { 'api_key' : api_key
, 'bug_status' : statuses
, 'target_milestone' : old_milestone
})
169 if bug
. change_milestone ( api_key
, old_milestone
, new_milestone
, comment
, add_known_to_fail
, doit
):
171 if modified
== limit
:
174 print ( ' \n Modified PRs: %d ' % modified
)
176 parser
= argparse
. ArgumentParser ( description
= '' )
177 parser
. add_argument ( 'api_key' , help = 'API key' )
178 parser
. add_argument ( '--remove' , nargs
= '?' , help = 'Remove a release from summary' )
179 parser
. add_argument ( '--add' , nargs
= '?' , help = 'Add a new release to summary, e.g. 6:7 will add 7 where 6 is included' )
180 parser
. add_argument ( '--limit' , nargs
= '?' , help = 'Limit number of bugs affected by the script' )
181 parser
. add_argument ( '--doit' , action
= 'store_true' , help = 'Really modify BUGs in the bugzilla' )
182 parser
. add_argument ( '--new-target-milestone' , help = 'Set a new target milestone, e.g. 4.9.3:4.9.4 will set milestone to 4.9.4 for all PRs having milestone set to 4.9.3' )
183 parser
. add_argument ( '--add-known-to-fail' , help = 'Set a new known to fail for all PRs affected by --new-target-milestone' )
184 parser
. add_argument ( '--comment' , help = 'Comment a PR for which we set a new target milestore' )
186 args
= parser
. parse_args ()
187 # Python3 does not have sys.maxint
188 args
. limit
= int ( args
. limit
) if args
. limit
!= None else 10 ** 10
190 if args
. remove
!= None or args
. add
!= None :
191 search ( args
. api_key
, args
. remove
, args
. add
, args
. limit
, args
. doit
)
192 if args
. new_target_milestone
!= None :
193 t
= args
. new_target_milestone
. split ( ':' )
195 replace_milestone ( args
. api_key
, args
. limit
, t
[ 0 ], t
[ 1 ], args
. comment
, args
. add_known_to_fail
, args
. doit
)