Example #1
0
def makepatch(ui, repo, name=None, pats=[], opts={}):
    """sets up the call for attic.createpatch and makes the call"""
    s = repo.attic
    force = opts.get('force')
    if name and s.exists(name) and name != s.applied and not force:
        raise util.Abort(_('attempting to overwrite existing patch'))
    if name and s.applied and name != s.applied and not force:
        raise util.Abort(_('a different patch is active'))
    if not name:
        name = s.applied
    if not name:
        raise util.Abort(_('you need to supply a patch name'))

    date, user, message = None, None, ''
    if s.applied:
        data = patch.extract(ui, open(s.join(s.applied), 'r'))
        tmpname, message, user, date, branch, nodeid, p1, p2 = data
        os.unlink(tmpname)
    msg = cmdutil.logmessage(opts)
    if not msg:
        msg = message
    if opts.get('edit'):
        msg = ui.edit(msg, ui.username())
    setupheaderopts(ui, opts)
    if opts.get('user'):
        user = opts['user']
    if not user:
        user = ui.username()
    if opts.get('date'):
        date = opts['date']
    if not date:
        date = util.makedate()
    date = util.parsedate(date)
    s.createpatch(repo, name, msg, user, date, pats, opts)
Example #2
0
def makepatch(ui, repo, name=None, pats=[], opts={}):
    """sets up the call for attic.createpatch and makes the call"""
    s = repo.attic
    force = opts.get('force')
    if name and s.exists(name) and name != s.applied and not force:
        raise util.Abort(_('attempting to overwrite existing patch'))
    if name and s.applied and name != s.applied and not force:
        raise util.Abort(_('a different patch is active'))
    if not name:
        name = s.applied
    if not name:
        raise util.Abort(_('you need to supply a patch name'))

    date, user, message = None, None, ''
    if s.applied:
        data = patch.extract(ui, open(s.join(s.applied), 'r'))
        tmpname, message, user, date, branch, nodeid, p1, p2 = data
        os.unlink(tmpname)
    msg = cmdutil.logmessage(opts)
    if not msg:
        msg = message
    if opts.get('edit'):
        msg = ui.edit(msg, ui.username())
    setupheaderopts(ui, opts)
    if opts.get('user'):
        user=opts['user']
    if not user:
        user = ui.username()
    if opts.get('date'):
        date=opts['date']
    if not date:
        date = util.makedate()
    date = util.parsedate(date)
    s.createpatch(repo, name, msg, user, date, pats, opts)
Example #3
0
 def apply(self, repo, patchfile, sim, force=False, **opts):
     """applies a patch and manages repo and attic state"""
     self.check_localchanges(repo, force)
     data = patch.extract(self.ui, open(self.join(patchfile), 'r'))
     tmpname, message, user, date, branch, nodeid, p1, p2 = data
     merge = False
     if repo.ui.configbool('attic', 'trymerge', default=True):
         try:
             if p1 and repo[p1]:
                 merge = True
         except error.RepoError:
             pass
     if merge:
         success = self._applymerge(repo, patchfile, sim, patchfile, p1,
                                     force=force, **opts)
     else:
         success = self._applypatch(repo, patchfile, sim,
                                     force=force, **opts)
     os.unlink(tmpname)
     if success:
         if opts.get('reverse'):
             self.applied = ''
             self.currentpatch = ''
         else:
             self.applied = patchfile
             self.currentpatch = patchfile
         self.persiststate()
     return success
Example #4
0
 def apply(self, repo, patchfile, sim, force=False, **opts):
     """applies a patch and manages repo and attic state"""
     self.check_localchanges(repo, force)
     data = patch.extract(self.ui, open(self.join(patchfile), 'r'))
     tmpname, message, user, date, branch, nodeid, p1, p2 = data
     merge = False
     if repo.ui.configbool('attic', 'trymerge', default=True):
         try:
             if p1 and repo[p1]:
                 merge = True
         except error.RepoError:
             pass
     if merge:
         success = self._applymerge(repo, patchfile, sim, patchfile, p1,
                                     force=force, **opts)
     else:
         success = self._applypatch(repo, patchfile, sim,
                                     force=force, **opts)
     os.unlink(tmpname)
     if success:
         if opts.get('reverse'):
             self.applied = ''
             self.currentpatch = ''
         else:
             self.applied = patchfile
             self.currentpatch = patchfile
         self.persiststate()
     return success
Example #5
0
def headerinfo(ui, repo, name):
    name = repo.attic.join(name)
    data = patch.extract(ui, open(name, 'r'))
    tmpname, message, user, date, branch, nodeid, p1, p2 = data
    os.unlink(tmpname)
    if not isinstance(message, str):
        message = '\n'.join(message)
    if not message or message.strip() == '':
        message = 'None\n'
    else:
        message = '\n' + message
    ui.write(_('user: %s\ndate: %s\nparent: %s\nmessage: %s') %
                  (user, date, p1, message))
Example #6
0
def headerinfo(ui, repo, name):
    name = repo.attic.join(name)
    data = patch.extract(ui, open(name, 'r'))
    tmpname, message, user, date, branch, nodeid, p1, p2 = data
    os.unlink(tmpname)
    if not isinstance(message, str):
        message = '\n'.join(message)
    if not message or message.strip() == '':
        message = 'None\n'
    else:
        message = '\n' + message
    ui.write(_('user: %s\ndate: %s\nparent: %s\nmessage: %s') %
                  (user, date, p1, message))
Example #7
0
 def detectPatches(self, paths):
     filepaths = []
     for p in paths:
         if not os.path.isfile(p):
             continue
         try:
             pf = open(p, 'rb')
             filename, message, user, date, branch, node, p1, p2 = \
                     patch.extract(self.repo.ui, pf)
             if filename:
                 filepaths.append(p)
                 os.unlink(filename)
         except Exception, e:
             pass
Example #8
0
 def detectPatches(self, paths):
     filepaths = []
     for p in paths:
         if not os.path.isfile(p):
             continue
         try:
             pf = open(p, 'rb')
             filename, message, user, date, branch, node, p1, p2 = \
                     patch.extract(self.repo.ui, pf)
             if filename:
                 filepaths.append(p)
                 os.unlink(filename)
         except Exception, e:
             pass
Example #9
0
def commitwrapper(orig, ui, repo, *args, **opts):
    s = repo.attic
    name = s.applied
    if not name:
        orig(ui, repo, *args, **opts)
    else:
        makepatch(ui, repo, name, [], opts)
        data = patch.extract(ui, open(s.join(name), 'r'))
        tmpname, m, u, d, branch, nodeid, p1, p2 = data
        os.unlink(tmpname)
        orig(ui, repo, message=m, logfile=None, user=u, date=d)

        if not opts.get('keep'):
            s.remove(name)
        s.resetdefault()
Example #10
0
def commitwrapper(orig, ui, repo, *args, **opts):
    s = repo.attic
    name = s.applied
    if not name:
        orig(ui, repo, *args, **opts)
    else:
        makepatch(ui, repo, name, [], opts)
        data = patch.extract(ui, open(s.join(name), 'r'))
        tmpname, m, u, d, branch, nodeid, p1, p2 = data
        os.unlink(tmpname)
        orig(ui, repo, message = m, logfile = None, user = u, date = d)

        if not opts.get('keep'):
            s.remove(name)
        s.resetdefault()
Example #11
0
    def __init__(self, patchpath, repo, patchHandle=None):
        """ Read patch context from file
        :param patchHandle: If set, then the patch is a temporary.
            The provided handle is used to read the patch and
            the patchpath contains the name of the patch. 
            The handle is NOT closed.
        """
        self._path = patchpath
        self._patchname = os.path.basename(patchpath)
        self._repo = repo
        if patchHandle:
            pf = patchHandle
            pf_start_pos = pf.tell()
        else:
            pf = open(patchpath)
        try:
            data = patch.extract(self._repo.ui, pf)
            tmpfile, msg, user, date, branch, node, p1, p2 = data
            if tmpfile:
                os.unlink(tmpfile)
        finally:
            if patchHandle:
                pf.seek(pf_start_pos)
            else:
                pf.close()
        if not msg and hasattr(repo, "mq"):
            # attempt to get commit message
            from hgext import mq

            msg = mq.patchheader(repo.mq.join(self._patchname)).message
            if msg:
                msg = "\n".join(msg)
        self._node = node
        self._user = user and hglib.toutf(user) or ""
        self._date = date and util.parsedate(date) or None
        self._desc = msg and msg or ""
        self._branch = branch and hglib.toutf(branch) or ""
        self._parents = []
        for p in (p1, p2):
            if not p:
                continue
            try:
                self._parents.append(repo[p])
            except (error.LookupError, error.RepoLookupError, error.RepoError):
                self._parents.append(p)
Example #12
0
  def __init__(self, bug, node):
    Attachment.__init__(self, bug, node)
    self.flags = list(sorted(Flag(bug, n) for n in node.findall('flag')))
    rawtext = base64.b64decode(node.find('data').text)
    filename, message, user, date, branch, nodeid, p1, p2 = \
        patch.extract(bug.settings.ui, StringIO.StringIO(rawtext))
    # for some reason, patch.extract writes a temporary file with the diff hunks
    if filename:
      fp = file(filename)
      try:
        # BugZilla is not explicit about patch encoding. We need to check it's utf-8.
        # utf-8: convert from 8-bit encoding to internal (16/32-bit) Unicode.
        self.data = fp.read().decode('utf-8')
      except UnicodeDecodeError:
        # Ftr, this could be due to the (included) message part: see later message block.
        bug.settings.ui.warn("Patch id=%s desc=\"%s\" diff data were discarded:\n" % (self.id, self.desc))
        # Print the exception without its traceback.
        sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
        # Can't do better than discard data:
        # trying |.decode('utf-8', 'replace')| as a fallback would be too risky
        #   if user imports the result then forgets to fix it.
        self.data = ''
      fp.close()
      os.remove(filename)
    else:
      self.data = ''

    # Remove seconds (which are always ':00') and timezone from the patch date:
    # keep 'yyyy-mm-dd hh:mn' only.
    self.date = date or node.find('date').text[:16]

    if user:
      try:
        # See previous self.data block about utf-8 handling.
        self.author = user.decode('utf-8')
      except UnicodeDecodeError:
        bug.settings.ui.warn("Patch id=%s desc=\"%s\" user data were discarded:\n" % (self.id, self.desc))
        sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
        user = None
    if not user:
      # Bugzilla v3.4.1+: "Email Addresses Hidden From Logged-Out Users"
      patchAttacherEmail = node.find('attacher').text
      # 'patchAttacherEmail' may not be enough, compare date too to be as precise as possible...
      posts = [p for p in self.bug.comments if p.date == self.date and p.who_email == patchAttacherEmail]
      who = posts[0].who
      for p in posts:
        if p.who == who:
          continue
        print "Warning: could not figure out exact author (multiple names for same date and email address)!"
        who = ""
        break
      # Email domain may need to be retrieved/added manually...
      self.author = "%s <%s>" % (
        # Scrub the :cruft and any '[...]' or '(...)' too from the username.
        re.sub("\[.*?\]|\(.*?\)|:\S+", "", who).strip(),
        patchAttacherEmail)

    self.commit_message = None
    # (Mercurial v1.4.3(-!?)) "No message" is extracted as '\n' :-/
    # Want to strip the message anyway.
    if message:
      try:
        # See previous self.data block about utf-8 handling.
        self.commit_message = message.decode('utf-8') \
                                     .strip()
      except UnicodeDecodeError:
        bug.settings.ui.warn("Patch id=%s desc=\"%s\" message data were discarded too:\n" % (self.id, self.desc))
        sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
        message = None
    if not self.commit_message:
      self.commit_message = self.bug.settings.msg_format % self.metadata
Example #13
0
    def __init__(self, bug, node):
        Attachment.__init__(self, bug, node)
        self.flags = list(sorted(Flag(bug, n) for n in node.findall('flag')))
        rawtext = base64.b64decode(node.find('data').text)

        data = patch.extract(bug.settings.ui, StringIO.StringIO(rawtext))
        # Mercurial 3.6 returns a dict. Previous versions a tuple.
        if isinstance(data, dict):
            filename = data.get('filename')
            message = data.get('message')
            user = data.get('user')
            date = data.get('date')
            branch = data.get('branch')
            nodeid = data.get('node')
            p1 = data.get('p1')
            p2 = data.get('p2')
        else:
            assert isinstance(data, tuple)
            filename, message, user, date, branch, nodeid, p1, p2 = data

        # for some reason, patch.extract writes a temporary file with the diff hunks
        if filename:
            fp = file(filename)
            try:
                # BugZilla is not explicit about patch encoding. We need to check it's utf-8.
                # utf-8: convert from 8-bit encoding to internal (16/32-bit) Unicode.
                self.data = fp.read().decode('utf-8')
                # Attempt to detect the start of the diff. Borrowed from:
                # http://selenic.com/hg/file/79e5de2bfa8c/mercurial/patch.py#l163
                diffre = re.compile(
                    r'^(?:Index:[ \t]|diff[ \t]|RCS file: |'
                    r'retrieving revision [0-9]+(\.[0-9]+)*$|'
                    r'---[ \t].*?^\+\+\+[ \t]|'
                    r'\*\*\*[ \t].*?^---[ \t])', re.MULTILINE | re.DOTALL)
                m = diffre.search(self.data)
                if m:
                    # Remove the patch header, since we'll be re-adding a cleaned up version later.
                    self.data = self.data[m.start(0):]
            except UnicodeDecodeError:
                # Ftr, this could be due to the (included) message part: see later message block.
                bug.settings.ui.warn(
                    "Patch id=%s desc=\"%s\" diff data were discarded:\n" %
                    (self.id, self.desc))
                # Print the exception without its traceback.
                sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
                # Can't do better than discard data:
                # trying |.decode('utf-8', 'replace')| as a fallback would be too risky
                #   if user imports the result then forgets to fix it.
                self.data = ''
            fp.close()
            os.remove(filename)
        else:
            self.data = ''

        # Remove seconds (which are always ':00') and timezone from the patch date:
        # keep 'yyyy-mm-dd hh:mn' only.
        self.date = date or node.find('date').text[:16]

        if user:
            try:
                # See previous self.data block about utf-8 handling.
                self.author = user.decode('utf-8')
            except UnicodeDecodeError:
                bug.settings.ui.warn(
                    "Patch id=%s desc=\"%s\" user data were discarded:\n" %
                    (self.id, self.desc))
                sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
                user = None
        if not user:
            # Bugzilla v3.4.1+: "Email Addresses Hidden From Logged-Out Users"
            patchAttacherEmail = node.find('attacher').text
            # 'patchAttacherEmail' may not be enough, compare date too to be as precise as possible...
            posts = [
                p for p in self.bug.comments
                if p.date == self.date and p.who_email == patchAttacherEmail
            ]
            who = posts[0].who
            for p in posts:
                if p.who == who:
                    continue
                print "Warning: could not figure out exact author (multiple names for same date and email address)!"
                who = ""
                break
            # Email domain may need to be retrieved/added manually...
            self.author = "%s <%s>" % (
                # Scrub the :cruft and any '[...]' or '(...)' too from the username.
                re.sub("\[.*?\]|\(.*?\)|:\S+", "", who).strip(),
                patchAttacherEmail)

        self.commit_message = None
        # (Mercurial v1.4.3(-!?)) "No message" is extracted as '\n' :-/
        # Want to strip the message anyway.
        if message:
            try:
                # See previous self.data block about utf-8 handling.
                self.commit_message = message.decode('utf-8').strip()
            except UnicodeDecodeError:
                bug.settings.ui.warn(
                    "Patch id=%s desc=\"%s\" message data were discarded too:\n"
                    % (self.id, self.desc))
                sys.excepthook(sys.exc_info()[0], sys.exc_info()[1], None)
                message = None
        if not self.commit_message:
            self.commit_message = self.bug.settings.msg_format % self.metadata