[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