diff options
author | Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 2020-03-26 18:01:36 -0400 |
---|---|---|
committer | Konstantin Ryabitsev <konstantin@linuxfoundation.org> | 2020-03-26 18:01:36 -0400 |
commit | 6de8a6106413068662ca2fa5a98ba2b6aa7f2d7b (patch) | |
tree | d6ac7295c40c740f09db0e9cc73e0052c11ad0e7 /b4/mbox.py | |
parent | 44ac4f1a78330f029343f31c46e46abc69a25121 (diff) | |
download | b4-6de8a6106413068662ca2fa5a98ba2b6aa7f2d7b.tar.gz |
Add initial "b4 pr" command set
While working on "pull-request exploder" stuff for achiving on
lore.kernel.org, I realized that this may be a useful set of features
for developers as well, so here is a very simple framework for handing
pull requests. Examples:
b4 pr <msgid>
- downloads that message
- parses the pull request
- checks that the remote tip is where the message says it should be
- makes sure the base-commit is present in the tree
- makes sure the tip commit isn't already in one of the branches
- checks if FETCH_HEAD already is at that commit
- if the above two checks pass, performs a git fetch
b4 pr --check <msgid>
Runs all of the checks above, but doesn't perform the actual fetch.
Useful if you don't remember if you've already processed a pull
request or not.
b4 pr --explode <msgid>
Runs basic sanity checks and then:
- performs a git fetch
- runs a "git format-patch" for base-commit..FETCH_HEAD
- adds the same to/from/cc headers as in the pull request
- properly threads each patch below the pull request
- saves that into a <msgid>.mbox file
The above is handy if you want to comment on something in a pull
request and not have to hunt around for sender/cc information.
Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
Diffstat (limited to 'b4/mbox.py')
-rw-r--r-- | b4/mbox.py | 115 |
1 files changed, 13 insertions, 102 deletions
@@ -13,11 +13,9 @@ import email.message import email.utils import re import time -import shutil import urllib.parse import xml.etree.ElementTree -import gzip import b4 @@ -26,81 +24,8 @@ from tempfile import mkstemp logger = b4.logger -def get_msgid_from_stdin(): - if not sys.stdin.isatty(): - message = email.message_from_string(sys.stdin.read()) - return message.get('Message-ID', None) - logger.error('Error: pipe a message or pass msgid as parameter') - sys.exit(1) - - -def get_pi_thread_by_url(t_mbx_url, savefile): - session = b4.get_requests_session() - resp = session.get(t_mbx_url) - if resp.status_code != 200: - logger.critical('Server returned an error: %s', resp.status_code) - return None - t_mbox = gzip.decompress(resp.content) - resp.close() - if not len(t_mbox): - logger.critical('No messages found for that query') - return None - with open(savefile, 'wb') as fh: - logger.debug('Saving %s', savefile) - fh.write(t_mbox) - return savefile - - -def get_pi_thread_by_msgid(msgid, config, cmdargs): - wantname = cmdargs.wantname - outdir = cmdargs.outdir - if wantname: - savefile = os.path.join(outdir, wantname) - else: - # Save it into msgid.mbox - savefile = '%s.t.mbx' % msgid - savefile = os.path.join(outdir, savefile) - - cachedir = b4.get_cache_dir() - cachefile = os.path.join(cachedir, '%s.pi.mbx' % urllib.parse.quote_plus(msgid)) - if os.path.exists(cachefile) and not cmdargs.nocache: - logger.debug('Using cached copy: %s', cachefile) - shutil.copyfile(cachefile, savefile) - return savefile - - # Grab the head from lore, to see where we are redirected - midmask = config['midmask'] % msgid - logger.info('Looking up %s', midmask) - session = b4.get_requests_session() - resp = session.head(midmask) - if resp.status_code < 300 or resp.status_code > 400: - logger.critical('That message-id is not known.') - return None - canonical = resp.headers['Location'].rstrip('/') - resp.close() - t_mbx_url = '%s/t.mbox.gz' % canonical - - loc = urllib.parse.urlparse(t_mbx_url) - if cmdargs.useproject: - logger.debug('Modifying query to use %s', cmdargs.useproject) - t_mbx_url = '%s://%s/%s/%s/t.mbox.gz' % ( - loc.scheme, loc.netloc, cmdargs.useproject, msgid) - logger.debug('Will query: %s', t_mbx_url) - logger.critical('Grabbing thread from %s', loc.netloc) - in_mbxf = get_pi_thread_by_url(t_mbx_url, '%s-loose' % savefile) - if not in_mbxf: - return None - in_mbx = mailbox.mbox(in_mbxf) - out_mbx = mailbox.mbox(savefile) - b4.save_strict_thread(in_mbx, out_mbx, msgid) - in_mbx.close() - out_mbx.close() - os.unlink(in_mbxf) - shutil.copyfile(savefile, cachefile) - return savefile - - -def mbox_to_am(mboxfile, config, cmdargs): +def mbox_to_am(mboxfile, cmdargs): + config = b4.get_main_config() outdir = cmdargs.outdir wantver = cmdargs.wantver wantname = cmdargs.wantname @@ -342,7 +267,7 @@ def get_newest_series(mboxfile): continue t_mbx_url = '%st.mbox.gz' % link savefile = mkstemp('b4-get')[1] - nt_mboxfile = get_pi_thread_by_url(t_mbx_url, savefile) + nt_mboxfile = b4.get_pi_thread_by_url(t_mbx_url, savefile) nt_mbx = mailbox.mbox(nt_mboxfile) # Append all of these to the existing mailbox new_adds = 0 @@ -371,32 +296,18 @@ def main(cmdargs): # Force nocache mode cmdargs.nocache = True - config = b4.get_main_config() - if not cmdargs.localmbox: - if not cmdargs.msgid: - logger.debug('Getting Message-ID from stdin') - msgid = get_msgid_from_stdin() - if msgid is None: - logger.error('Unable to find a valid message-id in stdin.') - sys.exit(1) + msgid = b4.get_msgid(cmdargs) + wantname = cmdargs.wantname + outdir = cmdargs.outdir + if wantname: + savefile = os.path.join(outdir, wantname) else: - msgid = cmdargs.msgid + # Save it into msgid.mbox + savefile = '%s.t.mbx' % msgid + savefile = os.path.join(outdir, savefile) - msgid = msgid.strip('<>') - # Handle the case when someone pastes a full URL to the message - matches = re.search(r'^https?://[^/]+/([^/]+)/([^/]+@[^/]+)', msgid, re.IGNORECASE) - if matches: - chunks = matches.groups() - msgid = chunks[1] - # Infer the project name from the URL, if possible - if chunks[0] != 'r': - cmdargs.useproject = chunks[0] - # Handle special case when msgid is prepended by id: or rfc822msgid: - if msgid.find('id:') >= 0: - msgid = re.sub(r'^\w*id:', '', msgid) - - mboxfile = get_pi_thread_by_msgid(msgid, config, cmdargs) + mboxfile = b4.get_pi_thread_by_msgid(msgid, savefile, useproject=cmdargs.useproject, nocache=cmdargs.nocache) if mboxfile is None: return @@ -414,7 +325,7 @@ def main(cmdargs): get_newest_series(threadmbox) if cmdargs.subcmd == 'am': - mbox_to_am(threadmbox, config, cmdargs) + mbox_to_am(threadmbox, cmdargs) if not cmdargs.localmbox: os.unlink(threadmbox) else: |