[oe-commits] org.oe.dev merge of '57d4969164263d2e6a79acef3ffe321fe7ac12ad'

oe commit openembedded-commits at lists.openembedded.org
Wed Oct 10 07:57:37 UTC 2007


merge of '57d4969164263d2e6a79acef3ffe321fe7ac12ad'
     and '9e58343e3062e654fd1504be00f174674696b0fa'

Author: oe at openembedded.org
Branch: org.openembedded.dev
Revision: c751859acd3640bd84cb596c1f3a4fe9bc0536be
ViewMTN: http://monotone.openembedded.org/revision/info/c751859acd3640bd84cb596c1f3a4fe9bc0536be
Files:
1
contrib/armmon_xfer
contrib/armmon_xfer/armmon_xfer.py
mtn:execute
true
contrib/mtn2git/mtn
contrib/mtn2git/git2mtn.py
contrib/mtn2git/mtn/__init__.py
contrib/mtn2git/mtn/authors.py
contrib/mtn2git/mtn/common.py
contrib/mtn2git/mtn/genproxy.py
contrib/mtn2git/mtn/mtn.py
contrib/mtn2git/mtn/utility.py
contrib/mtn2git/mtn2git.py
contrib/mtn2git/status.py
Diffs:

#
# mt diff -r57d4969164263d2e6a79acef3ffe321fe7ac12ad -rc751859acd3640bd84cb596c1f3a4fe9bc0536be
#
# 
# 
# add_dir "contrib/armmon_xfer"
# 
# add_file "contrib/armmon_xfer/armmon_xfer.py"
#  content [92a8b202efc3a1fd444effb72f40176212ee947e]
# 
#   set "contrib/armmon_xfer/armmon_xfer.py"
#  attr "mtn:execute"
# value "true"
# 
============================================================
--- contrib/armmon_xfer/armmon_xfer.py	92a8b202efc3a1fd444effb72f40176212ee947e
+++ contrib/armmon_xfer/armmon_xfer.py	92a8b202efc3a1fd444effb72f40176212ee947e
@@ -0,0 +1,150 @@
+#!/usr/bin/python
+
+# Small utility to upload kernel and/or ramdisk to
+# the compulab board through the ARMmon firmware.
+# Requires pyserial : http://pyserial.sourceforge.net
+# author: Tobias Pflug
+
+import sys, os, serial, getopt, atexit, re
+
+# regular expression to match valid IPv4 addresses
+ipv4_regex = r"\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b"
+
+def wait_flash_complete():
+    while 1:
+        data = s.readline()
+        if quiet != 1:
+            print data,
+        if data.split(" ")[0] == "Finished":
+            break
+
+def test_armmon():
+    # write some nonsense to the monitor and
+    # check if armmon replies accordingly
+    s.write("nonsense\n")
+    s.timeout=2
+    s.read(len("nonsense\n")+1)
+    data = s.read(len("Illegal"))
+    if data.split(" ")[0] != "Illegal":
+        sys.exit("Error: ARMmon not responding. Linux running maybe?")
+    s.timeout=None
+    s.flushInput()
+    s.flushOutput()
+
+
+def usage():
+    sys.stderr.write("""USAGE: %s [options] <server ip>
+    armmon_xfer - data upload tool for cmx270/ARMmon
+
+    options:
+    -p, --port=PORT:        serial port, default='/dev/ttyUSB0'
+    -k, --kernel=KERNEL:    upload and flash kernel image KERNEL
+    -r, --ramdisk=RAMDISK:  upload and flash ramdisk image RAMDISK
+    -b, --bootos:           boot Linux
+    -R, --reboot:           reboot cmx270
+    -q, --quiet             be quiet, little output
+    -h, --help:             print this help screen
+
+""" % (sys.argv[0],))
+
+if __name__ == '__main__':
+
+    port = "/dev/ttyUSB0"
+    baud = 38400
+    kernel = None
+    ramdisk = None
+    boot = None
+    reboot = None
+    quiet = None
+    tftp_ip = None
+
+    if len(sys.argv) < 2:
+        usage()
+        sys.exit(0)
+
+    # parse command line
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:],
+                "p:k:r:bRhq",
+                ["port=", "kernel=","ramdisk=","bootos","reboot","help","quiet"]
+                )
+    except getopt.GetoptError:
+        usage()
+        sys.exit(2)
+
+    for o, a in opts:
+        if o in ("-h","--help"):
+            usage()
+            sys.exit()
+        elif o in ("-k","--kernel"):
+            kernel = a
+        elif o in ("-r","--ramdisk"):
+            ramdisk = a
+        elif o in ("-b","--bootos"):
+            boot = 1
+        elif o in ("-R","--reboot"):
+            reboot = 1
+        elif o in ("-p","--port"):
+            port = o
+        elif o in ("-q","--quiet"):
+            quiet = 1
+
+    # check for arguments and validate IP address
+    # when required by commands
+    if len(args)>0 and re.match(ipv4_regex,args[0]):
+        tftp_ip = args[0]
+    else: 
+        if kernel or ramdisk:
+            sys.exit("Error: invalid IP address!")
+
+    try:
+         s = serial.Serial('/dev/ttyUSB0',38400)
+    except:
+         sys.stderr.write("Error: Could not open port: %s\n" % (port))
+         sys.exit(1)
+
+    # test if armmon is responding on bogus input
+    test_armmon()
+
+    # carry out commands     
+
+    if reboot:
+        print "Rebooting compulab ..."
+        s.write("reboot\n")
+        s.write("y\n")
+        s.write("y\n")
+        s.close()
+        sys.exit(0)
+
+    if kernel:
+        print "Downloading kernel ..."
+        cmd = "download kernel tftp %s %s\n" % (kernel,tftp_ip)
+        s.write(cmd)
+        data = s.readline()
+        data = s.readline()
+
+        print "Flashing kernel ..."
+        cmd = "flash kernel\n"
+        s.write(cmd)
+        wait_flash_complete()
+
+
+    if ramdisk:
+        print "Downloading ramdisk ..."
+        cmd = "download ramdisk tftp %s %s\n" % (ramdisk,tftp_ip)
+        s.write(cmd)
+        s.readline()
+        s.readline()
+
+        print "Flashing ramdisk ..."
+        cmd = "flash ramdisk\n"
+        s.write(cmd)
+        wait_flash_complete()
+
+    if boot:
+        print "Booting Linux ..."
+        s.write("bootos\n")
+
+    s.close()
+    sys.exit(0)


#
# mt diff -r9e58343e3062e654fd1504be00f174674696b0fa -rc751859acd3640bd84cb596c1f3a4fe9bc0536be
#
# 
# 
# add_dir "contrib/mtn2git/mtn"
# 
# add_file "contrib/mtn2git/git2mtn.py"
#  content [052dc79ba2fb8ef0ea324e55549ae13233d144f4]
# 
# add_file "contrib/mtn2git/mtn/__init__.py"
#  content [512093425c7be8fc6da16e10a7cffcda07e45254]
# 
# add_file "contrib/mtn2git/mtn/authors.py"
#  content [0ed0661cf3ddf1b402a73dfc1ff0fccc64ad05f1]
# 
# add_file "contrib/mtn2git/mtn/common.py"
#  content [a071eb4d76e1a83824dacd8188199e00ad87fff1]
# 
# add_file "contrib/mtn2git/mtn/genproxy.py"
#  content [408f46a3f5fe0d792eb62e92a8faaf5c28c67a54]
# 
# add_file "contrib/mtn2git/mtn/mtn.py"
#  content [b7992918c918fb72a18396be361fc5eba1784e57]
# 
# add_file "contrib/mtn2git/mtn/utility.py"
#  content [78cd2c53af05e63bb76c097dc832b6f75394e40d]
# 
# add_file "contrib/mtn2git/mtn2git.py"
#  content [f336e19760df662e35b161bf5791041c5a6e1824]
# 
# add_file "contrib/mtn2git/status.py"
#  content [d3682877d9debb3e8439b6a0558bb11e6e2262b0]
# 
#   set "contrib/mtn2git/git2mtn.py"
#  attr "mtn:execute"
# value "true"
# 
#   set "contrib/mtn2git/mtn/genproxy.py"
#  attr "mtn:execute"
# value "true"
# 
#   set "contrib/mtn2git/mtn2git.py"
#  attr "mtn:execute"
# value "true"
# 
============================================================
--- contrib/mtn2git/git2mtn.py	052dc79ba2fb8ef0ea324e55549ae13233d144f4
+++ contrib/mtn2git/git2mtn.py	052dc79ba2fb8ef0ea324e55549ae13233d144f4
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+"""
+  Copyright (C) 2006, 2007 Holger Hans Peter Freyther
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this software and associated documentation files (the "Software"), to deal
+  in the Software without restriction, including without limitation the rights
+  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+  copies of the Software, and to permit persons to whom the Software is
+  furnished to do so, subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+  THE SOFTWARE.
+"""
+
+#############
+#
+# Use: This tool can merge one git-branch back to one branch in monotone
+#
+# Discussion:
+#   Merging from git to a monotone branch. Currently I see two modes which
+#   should be supported.
+#
+#    a) linear development. Only a couple of changes are done on top of the
+#       branch and nothing get merged. In this case we can merge everything
+#       back and each rev gets a cert with the branch.
+#       This should be possible using programs like git-rebase.
+#    b) we have merges inside our git-rev-list history. This means we need to
+#       merge every revision and can't attach any branch certs to the revision.
+#       And once we are done with this we will create a propagate like commit
+#       entry and we can give that new revision a cert with the branch name.
+#
+#       This means working in git is treated like a branch!
+#
+#       One difficulty is with git. This propagate like commit will create a new revision
+#       in monotone but none in git as both trees/manifests are the same. So what we have
+#       to make sure is to use the latest mtn revision for a given mark/git revision. This
+#       is where mtn2git.py needs to help. We will save a list of mtn revisions that have the
+#       same git version and then will read every of them and check the branch certs and will
+#       use the one matching our target branch!
+#############
============================================================
--- contrib/mtn2git/mtn/__init__.py	512093425c7be8fc6da16e10a7cffcda07e45254
+++ contrib/mtn2git/mtn/__init__.py	512093425c7be8fc6da16e10a7cffcda07e45254
@@ -0,0 +1,6 @@
+from mtn import Automate, Operations
+
+__all__ = [
+    "Automate",
+    "Operations"
+    ]
============================================================
--- contrib/mtn2git/mtn/authors.py	0ed0661cf3ddf1b402a73dfc1ff0fccc64ad05f1
+++ contrib/mtn2git/mtn/authors.py	0ed0661cf3ddf1b402a73dfc1ff0fccc64ad05f1
@@ -0,0 +1,11 @@
+authors='''Authors:
+Grahame Bowland <grahame at angrygoats.net>
+
+Contributors:
+Matt Johnston <matt at ucc.asn.au>
+Nathaniel Smith <njs at pobox.com>
+Bruce Stephens <monotone at cenderis.demon.co.uk>
+Lapo Luchini <lapo at lapo.it>
+David Reiss <davidn at gmail.com>
+
+'''
============================================================
--- contrib/mtn2git/mtn/common.py	a071eb4d76e1a83824dacd8188199e00ad87fff1
+++ contrib/mtn2git/mtn/common.py	a071eb4d76e1a83824dacd8188199e00ad87fff1
@@ -0,0 +1,49 @@
+
+import datetime
+import time
+import fcntl
+import os
+import signal
+import traceback
+import sys
+
+def parse_timecert(value):
+    return apply(datetime.datetime, time.strptime(value, "%Y-%m-%dT%H:%M:%S")[:6])
+
+def set_nonblocking(fd):
+	fl = fcntl.fcntl(fd, fcntl.F_GETFL)
+	fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)
+
+def terminate_popen3(process):
+        print >> sys.stderr, ("[%s] stopping process: %s" % (os.getpid(), process.pid))
+        try:
+            process.tochild.close()
+            process.fromchild.close()
+            process.childerr.close()
+            if process.poll() == -1:
+                # the process is still running, so kill it.
+                os.kill(process.pid, signal.SIGKILL)
+            process.wait()
+        except:
+            print >> sys.stderr, ("%s failed_to_stop %s (%s)" % (os.getpid(), process.pid, traceback.format_exc()))
+
+def ago(event):
+    def plural(v, singular, plural):
+        if v == 1:
+            return "%d %s" % (v, singular)
+        else:
+            return "%d %s" % (v, plural)
+    now = datetime.datetime.utcnow()
+    ago = now - event
+    if ago.days > 0:
+        rv = "%s" % (plural(ago.days, "day", "days"))
+    elif ago.seconds > 3600:
+        hours = ago.seconds / 3600
+        minutes = (ago.seconds - (hours * 3600)) / 60
+        rv = "%s" % (plural(hours, "hour", "hours"))
+    else:
+        minutes = ago.seconds / 60
+        seconds = (ago.seconds - (minutes * 60))
+        rv = "%s" % (plural(minutes, "minute", "minutes"))
+    return rv
+
============================================================
--- contrib/mtn2git/mtn/genproxy.py	408f46a3f5fe0d792eb62e92a8faaf5c28c67a54
+++ contrib/mtn2git/mtn/genproxy.py	408f46a3f5fe0d792eb62e92a8faaf5c28c67a54
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+class GeneratorProxy(object):
+    def __init__(self, generator):
+        self.generator = generator
+    def __iter__(self):
+        return self
+    def next(self):
+        return self.generator.next()
+
+class Seedy(GeneratorProxy):
+    def __del__(self):
+        print "testing"
+        
+def test():
+    yield 2
+    yield 3
+    yield 4
+
+if __name__ == '__main__':
+    a = test()
+    b = Seedy(test())
+    for i in b:
+        print i
+    
============================================================
--- contrib/mtn2git/mtn/mtn.py	b7992918c918fb72a18396be361fc5eba1784e57
+++ contrib/mtn2git/mtn/mtn.py	b7992918c918fb72a18396be361fc5eba1784e57
@@ -0,0 +1,419 @@
+
+import os
+import re
+import fcntl
+import pipes
+import select
+import threading
+import popen2
+from common import set_nonblocking, terminate_popen3
+from traceback import format_exc
+import genproxy
+import sys
+
+# regular expressions that are of general use when 
+# validating monotone output
+def group_compile(r):
+    return re.compile('('+r+')')
+
+hex_re = r'[A-Fa-f0-9]*'
+hex_re_c = group_compile(hex_re)
+revision_re = r'[A-Fa-f0-9]{40}'
+revision_re_c = group_compile(revision_re)
+name_re = r'^[\S]+'
+name_re_c = group_compile(name_re)
+
+class MonotoneException(Exception):
+    pass
+
+class Revision(str):
+    def __init__(self, v):
+        # special case that must be handled: empty (initial) revision ID ''
+        str.__init__(v)
+        self.obj_type = "revision"
+        if v != '' and not revision_re_c.match(self):
+            raise MonotoneException("Not a valid revision ID: %s" % (v))
+    def abbrev(self):
+        return '[' + self[:8] + '..]'
+
+class Author(str):
+    def __init__(self, v):
+        str.__init__(v)
+        self.obj_type = "author"
+        
+class Runner:
+    def __init__(self, monotone, database):
+        self.base_command = [monotone, "--db=%s" % pipes.quote(database)]
+
+packet_header_re = re.compile(r'^(\d+):(\d+):([lm]):(\d+):')
+
+class Automate(Runner):
+    """Runs commands via a particular monotone process. This 
+       process is started the first time run() is called, and 
+       stopped when this class instance is deleted or the stop()
+       method is called.
+       
+       If an error occurs, the monotone process may need to be 
+       stopped and a new one created.
+       """
+    def __init__(self, *args, **kwargs):
+        Runner.__init__(*[self] + list(args), **kwargs)
+        self.lock = threading.Lock()
+        self.process = None
+
+    def stop(self):
+        if not self.process:
+            return
+        terminate_popen3(self.process)
+        self.process = None
+ 
+    def __process_required(self):
+        if self.process != None:
+            return
+        to_run = self.base_command + ['automate', 'stdio']
+        self.process = popen2.Popen3(to_run, capturestderr=True)
+        # breaks down with toposort and a lot of input
+        #map (set_nonblocking, [ self.process.fromchild,
+        #                        self.process.tochild,
+        #                        self.process.childerr ])
+        map (set_nonblocking, [ self.process.fromchild,
+                                self.process.childerr ])
+
+    def run(self, *args, **kwargs):
+        print >> sys.stderr, (("automate is running:", args, kwargs))
+
+        lock = self.lock
+        stop = self.stop
+        class CleanRequest(genproxy.GeneratorProxy):
+            def __init__(self, *args, **kwargs):
+                genproxy.GeneratorProxy.__init__(self, *args, **kwargs)
+
+                # nb; this used to be False, but True seems to behave more sensibly.
+                # in particular, if someone holds down Refresh sometimes the code 
+                # gets here before __del__ is called on the previous iterator, 
+                # causing a pointless error to occur
+                if not lock.acquire(True):
+                    # I've checked; this exception does _not_ cause __del__ to run, so 
+                    # we don't accidentally unlock a lock below
+                    raise MonotoneException("Automate request cannot be called: it is already locked! This indicates a logic error in ViewMTN; please report.")
+
+            def __del__(self):
+                def read_any_unread_output():
+                    try:
+                        # this'll raise StopIteration if we're done
+                        self.next()
+                        # okay, we're not done..
+                        print >> sys.stderr, ("warning: Automate output not completely read; reading manually.")
+                        for stanza in self:
+                            pass
+                    except StopIteration:
+                        pass
+
+                try:
+                    read_any_unread_output()
+                    lock.release()
+                except:
+                    print >> sys.stderr, ("exception cleaning up after Automation; calling stop()!")
+                    stop()
+
+        return CleanRequest(self.__run(*args, **kwargs))
+
+    def __run(self, command, args):
+        enc = "l%d:%s" % (len(command), command)
+        enc += ''.join(["%d:%s" % (len(x), x) for x in args]) + 'e'
+
+        # number of tries to get a working mtn going..
+        for i in xrange(2):
+            self.__process_required()
+            try:
+                self.process.tochild.write(enc)
+                self.process.tochild.flush()
+                break
+            except:
+                # mtn has died underneath the automate; restart it
+                print >> sys.stderr, ("exception writing to child process; attempting restart: %s" % format_exc())
+                self.stop()
+
+        import sys
+        def read_result_packets():
+            buffer = ""
+            while True:
+                r_stdin, r_stdout, r_stderr = select.select([self.process.fromchild], [], [], None)
+                if not r_stdin and not r_stdout and not r_stderr:
+                    break
+
+                if self.process.fromchild in r_stdin:
+                    data = self.process.fromchild.read()
+                    if data == "":
+                        break
+                    buffer += data
+
+                # loop, trying to get complete packets out of our buffer
+                complete, in_packet = False, False
+                while not complete and buffer != '':
+                    if not in_packet:
+                        m = packet_header_re.match(buffer)
+                        if not m:
+                            break
+                        in_packet = True
+                        cmdnum, errnum, pstate, length = m.groups()
+                        errnum = int(errnum)
+                        length = int(length)
+                        header_length = m.end(m.lastindex) + 1 # the '1' is the colon
+
+                    if len(buffer) < length + header_length:
+                        # not enough data read from client yet; go round
+                        break
+                    else:
+                        result = buffer[header_length:header_length+length]
+                        buffer = buffer[header_length+length:]
+                        complete = pstate == 'l'
+                        in_packet = False
+                        yield errnum, complete, result
+
+                if complete:
+                    break
+                
+        # get our response, and yield() it back one line at a time
+        code_max = -1
+        data_buf = ''
+        for code, is_last, data in read_result_packets():
+            if code and code > code_max:
+                code_max = code
+            data_buf += data
+            while True:
+                nl_idx = data_buf.find('\n')
+                if nl_idx == -1:
+                    break
+                yield data_buf[:nl_idx+1]
+                data_buf = data_buf[nl_idx+1:]
+        # left over data?
+        if data_buf:
+            yield data_buf
+        if code_max > 0:
+            raise MonotoneException("error code %d in automate packet." % (code_max))
+
+class Standalone(Runner):
+    """Runs commands by running monotone. One monotone process 
+       per command"""
+
+    def run(self, command, args):
+        # as we pass popen3 as sequence, it executes monotone with these 
+        # arguments - and does not pass them through the shell according 
+        # to help(os.popen3)
+#       print(("standalone is running:", command, args))
+        to_run = self.base_command + [command] + args
+        process = popen2.Popen3(to_run, capturestderr=True)
+        for line in process.fromchild:
+            yield line
+        stderr_data = process.childerr.read()
+        if len(stderr_data) > 0:
+            raise MonotoneException("data on stderr for command '%s': %s" % (command, 
+                                                                             stderr_data))
+        terminate_popen3(process)
+
+class MtnObject:
+    def __init__(self, obj_type):
+        self.obj_type = obj_type
+
+class Tag(MtnObject):
+    def __init__(self, name, revision, author, branches):
+        MtnObject.__init__(self, "tag")
+        self.name, self.revision, self.author, self.branches = name, Revision(revision), author, branches
+
+class Branch(MtnObject):
+    def __init__(self, name):
+        MtnObject.__init__(self, "branch")
+        self.name = name
+
+class File(MtnObject):
+    def __init__(self, name, in_revision):
+        MtnObje%s
>>> DIFF TRUNCATED @ 16K






More information about the Openembedded-commits mailing list