Author: saces
Date: 2008-11-26 22:37:17 +0000 (Wed, 26 Nov 2008)
New Revision: 23895

Modified:
   trunk/apps/pyFreenetHg/FreenetHg.py
   trunk/apps/pyFreenetHg/ReadMe.html
Log:
version 0.1:
 - major refactoring, its now a real "single file tool", no non-python-builtin 
dependencies
 - cleanup, remove redundant/obsolete functions 

Modified: trunk/apps/pyFreenetHg/FreenetHg.py
===================================================================
--- trunk/apps/pyFreenetHg/FreenetHg.py 2008-11-26 18:05:32 UTC (rev 23894)
+++ trunk/apps/pyFreenetHg/FreenetHg.py 2008-11-26 22:37:17 UTC (rev 23895)
@@ -6,12 +6,12 @@
 # To Public License, Version 2, as published by Sam Hocevar. See
 # http://sam.zoy.org/wtfpl/COPYING for more details. */

-
 import os, time
 import tempfile
+import random
+import socket
 import sys
 import dircache
-import fcp

 from nntplib import NNTP
 from StringIO import StringIO
@@ -19,9 +19,310 @@

 from mercurial import hg
 from mercurial import commands
-from mercurial import repo,cmdutil,util,ui,revlog,node
+from mercurial import repo, cmdutil, util, ui, revlog, node
 from mercurial.node import bin

+#
+# fcp rape begin
+#
+
+# the stuff below is treated as lib, so it should not refer to hg or other 
non-python-builtin stuff
+
+REQUIRED_NODE_VERSION=1183
+REQUIRED_EXT_VERSION=26
+
+DEFAULT_FCP_HOST = "127.0.0.1"
+DEFAULT_FCP_PORT = 9481
+DEFAULT_TIMEOUT = 300
+
+# utils
+def _getUniqueId():
+    """Allocate a unique ID for a request"""
+    timenum = int( time.time() * 1000000 );
+    randnum = random.randint( 0, timenum );
+    return "id" + str( timenum + randnum );
+
+# asynchronous stuff (single thread)
+class FCPIOConnection(object):
+    """class for real i/o and format helpers"""
+    
+    def __init__(self, host, port, timeout):
+        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.socket.settimeout(timeout)
+        try:
+            self.socket.connect((host, port))
+        except Exception, e:
+            raise Exception("Failed to connect to %s:%s - %s" % (host, port, 
e))
+        pass
+    
+    def __del__(self):
+        """object is getting cleaned up, so disconnect"""
+        try:
+            self.socket.close()
+        except:
+            pass
+        
+    def _readline(self):
+        buf = []
+        while True:
+            c = self.socket.recv(1)
+            if c == '\n':
+                break
+            buf.append(c)
+        ln = "".join(buf)
+        return ln
+    
+    def read(self, n):
+        chunks = []
+        remaining = n
+        while remaining > 0:
+            chunk = self.socket.recv(remaining)
+            chunklen = len(chunk)
+            if chunk:
+                chunks.append(chunk)
+            else:
+                raise Exception("FCP socket closed by node")
+            remaining -= chunklen
+        buf = "".join(chunks)
+        print "testi: in:<"+str(len(buf))+" Bytes of data>" 
+        return buf
+
+    def readEndMessage(self):
+        #the first line is the message name
+        messagename = self._readline()
+        print "testi: in:"+messagename
+        items = {}
+        while True:
+            line = self._readline();
+            print "testi: in:"+line
+            if (len(line.strip()) == 0):
+                continue # an empty line, jump over
+            
+            if line in ['End', 'EndMessage', 'Data']:
+                endmarker = line
+                break
+            
+            # normal 'key=val' pairs left
+            k, v = line.split("=", 1)
+            items[k] = v
+             
+        return FCPMessage(messagename, items, endmarker)
+    
+    def _sendLine(self, line):
+        print "testi: out:"+line
+        self.socket.sendall(line+"\n")
+    
+    def _sendMessage(self, messagename, hasdata=False, **kw):
+        self._sendLine(messagename)
+        for k, v in kw.items():
+            line = k + "=" + str(v)
+            self._sendLine(line)
+        if kw.has_key("DataLength") or hasdata:
+            self._sendLine("Data")
+        else:
+            self._sendLine("EndMessage")
+    
+    def _sendCommand(self, messagename, hasdata, kw):
+        self._sendLine(messagename)
+        for k, v in kw.items():
+            line = k + "=" + str(v)
+            self._sendLine(line)
+        if kw.has_key("DataLength") or hasdata:
+            self._sendLine("Data")
+        else:
+            self._sendLine("EndMessage")
+    
+    def _sendData(self, data):
+        print "testi: out:<"+str(len(data))+" Bytes of data>" 
+        self.socket.sendall(data)
+
+class FCPConnection(FCPIOConnection):
+    """class for low level fcp protocol i/o"""
+    
+    def __init__(self, host, port, timeout):
+        """c'tor leaves a ready to use connection (hello done)"""
+        FCPIOConnection.__init__(self, host, port, timeout)
+        self._helo()
+        
+    def _helo(self):
+        """perform the initial FCP protocol handshake"""
+        name = _getUniqueId()
+        self._sendMessage("ClientHello", Name=name, ExpectedVersion="2.0")
+        msg = self.readEndMessage()
+        if not msg.isMessageName("NodeHello"):
+            raise Exception("Node helo failed: %s" % (msg.getMessageName()))
+        
+        # check versions
+        version = msg.getIntValue("Build")
+        if version < REQUIRED_NODE_VERSION:
+            raise Exception("Node to old. Found %d, but need %d" % (version, 
REQUIRED_NODE_VERSION))
+        extversion = msg.getIntValue("ExtBuild")
+        if extversion < REQUIRED_EXT_VERSION:
+            raise Exception("Node-ext to old. Found %d, but need %d" % 
(extversion, REQUIRED_EXT_VERSION))
+    
+    def sendCommand(self, command):
+        self._sendCommand(command.getCommandName(), command.hasData(), 
command.getItems())
+        
+    def sendCommand(self, command, data):
+        self._sendCommand(command.getCommandName(), True, command.getItems())
+        self._sendData(data)
+        
+    def write(self, data):
+        self._sendData(data)
+            
+class FCPCommand(object):
+    """class for client to node messages"""
+    
+    _items = {}
+    
+    def __init__(self, name, identifier=None):
+        self._name = name
+        if None == identifier:
+            self._items['Identifier'] = _getUniqueId()
+        else:
+            self._items['Identifier'] = identifier
+
+    def getCommandName(self):
+        return self._name;
+    
+    def getItems(self):
+        return self._items;
+    
+    def setItem(self, name, value):
+        self._items[name] = value;
+    
+    def hasData(self):
+        if self._items.has_key("DataLength"):
+            return True
+        else:
+            return False 
+            
+class FCPMessage(object):
+    """class for node to client messages"""
+    _items = {}
+    _messagename = ""
+    _endmarker = ""
+    
+    def __init__(self, messagename, items, endmarker):
+        self._messagename = messagename
+        self._endmarker = endmarker
+        self._items = items 
+    
+    def isMessageName(self, testname):
+        if self._messagename in testname:
+            return True
+        else:
+            return False
+        
+    def getMessageName(self):
+        return self._messagename
+        
+    def getIntValue(self, name):
+        return int(self._items[name])
+    
+    def getValue(self, name):
+        return self._items[name]
+
+# asynchronous stuff (thread save)
+class FCPJob(object):
+    """abstract class for asynchronous jobs, they may use more then one fcp 
command and/or interact with the node in a complex manner"""
+
+class FCPSession(object):
+    """class for managing/running FCPJobs"""
+    
+# the stuff above is treated as lib, so it should not refer to hg or other 
non-python-builtin stuff
+
+class HgFCPConnection(FCPConnection):
+    
+    def __init__(self, ui, **opts):
+        # defaults
+        host = DEFAULT_FCP_HOST
+        port = DEFAULT_FCP_PORT 
+        timeout = DEFAULT_TIMEOUT
+        
+        host = ui.config('freenethg', 'fcphost')
+        port = ui.config('freenethg', 'fcpport')
+        
+        #host = opts.get('host', env.get("FCP_HOST", DEFAULT_FCP_HOST))
+        #port = opts.get('port', env.get("FCP_PORT", DEFAULT_FCP_PORT))
+        
+        # command line overwrites
+        if opts.get('fcphost'):
+            host = opts['fcphost']
+        if opts.get('fcpport'):
+            port = opts['fcpport']
+        if opts.get('fcptimeout'):
+            timeout = opts['fcptimeout']
+        
+        FCPConnection.__init__(self, host, int(port), timeout)
+        
+def hgBundlePut(connection, data):
+    
+    putcmd = FCPCommand('ClientPut')
+    putcmd.setItem('Verbosity', -1)
+    putcmd.setItem('URI', "CHK@")
+    putcmd.setItem('MaxRetries', -1)
+    putcmd.setItem('Metadata.ContentType', 'mercurial/bundle')
+    putcmd.setItem('DontCompress', 'false')
+    putcmd.setItem('PriorityClass', '1')
+    putcmd.setItem('UploadFrom', 'direct')
+    putcmd.setItem('DataLength', len(data))
+    
+    connection.sendCommand(putcmd)
+    connection.write(data)
+    
+    while True:
+        msg = connection.readEndMessage()
+        
+        if msg.isMessageName('PutSuccessful'):
+            return msg.getValue('URI')
+        
+        if msg.isMessageName('ProtocolError'):
+            raise Exception("ProtocolError(%d) - %s: %s" % 
(msg.getIntValue('Code'), msg.getValue('CodeDescription'), 
msg.getValue('ExtraDescription')))
+            
+        if msg.isMessageName('PutFailed'):
+            raise Exception("This should really not happen!")
+        
+        if msg.isMessageName('SimpleProgress'):
+            print "Succeeded: %d  -  Required: %d  -  Total: %d  -  Failed: %d 
 -  Final: %s" % (msg.getIntValue('Succeeded'), msg.getIntValue('Required'), 
msg.getIntValue('Total'), msg.getIntValue('FatallyFailed'), 
msg.getValue('FinalizedTotal'))
+            continue
+
+        print msg.getMessageName()
+
+def hgBundleGet(connection, uri):
+    
+    getcmd = FCPCommand('ClientGet')
+    getcmd.setItem('Verbosity', -1)
+    getcmd.setItem('URI', uri)
+    getcmd.setItem('MaxRetries', 5)
+    getcmd.setItem('PriorityClass', '1')
+    getcmd.setItem('ReturnType', 'direct')
+    
+    connection.sendCommand(getcmd)
+    
+    while True:
+        msg = connection.readEndMessage()
+        
+        if msg.isMessageName('AllData'):
+            size = msg.getIntValue('DataLength');
+            return connection.read(size)
+        
+        if msg.isMessageName('ProtocolError'):
+            raise Exception("ProtocolError(%d) - %s: %s" % 
(msg.getIntValue('Code'), msg.getValue('CodeDescription'), 
msg.getValue('ExtraDescription')))
+            
+        if msg.isMessageName('GetFailed'):
+            raise Exception("This should really not happen!")
+        
+        if msg.isMessageName('SimpleProgress'):
+            print "Succeeded: %d  -  Required: %d  -  Total: %d  -  Failed: %d 
 -  Final: %s" % (msg.getIntValue('Succeeded'), msg.getIntValue('Required'), 
msg.getIntValue('Total'), msg.getIntValue('FatallyFailed'), 
msg.getValue('FinalizedTotal'))
+            continue
+
+        print msg.getMessageName()
+            
+#
+# fcp rape end
+#
+
 class IndexPageMaker(object):
     """class for generate an index page"""

@@ -89,8 +390,8 @@
         subject_addon = None

         try:
-            f = open(template_path,'r')
-            subject_addon = f.readline().replace('\n','').replace('\r\n','')
+            f = open(template_path, 'r')
+            subject_addon = f.readline().replace('\n', '').replace('\r\n', '')
             user_template = f.read()
             f.close()
         except Exception, e:
@@ -102,7 +403,7 @@

     def post_updatestatic(self, notify_data, template_path=None):
         uri = notify_data['uri']
-        uri = uri.endswith('/') and uri[:-1] or uri
+        uri = uri.endswith('/') and uri[: - 1] or uri
         repository_name = uri.split('/')[1]
         repository_version = uri.split('/')[2]

@@ -126,7 +427,7 @@
         template_data = {'body':body,
                          'subject':subject,
                          'fms_user':self.fms_user,
-                         'fms_groups':self.fms_groups,}
+                         'fms_groups':self.fms_groups, }

         article = StringIO(self.nntp_msg_template.substitute(template_data))
         result = self.post(article)
@@ -164,7 +465,7 @@
             template_data = {'body':body,
                              'subject':subject,
                              'fms_user':self.fms_user,
-                             'fms_groups':self.fms_groups,}
+                             'fms_groups':self.fms_groups, }

             article = 
StringIO(self.nntp_msg_template.substitute(template_data))
             result = self.post(article)
@@ -185,21 +486,21 @@

     def notify(self):
         uiw = self.ui.walkconfig()
-        trigger = self.ui.config('freenethg','notify')
+        trigger = self.ui.config('freenethg', 'notify')

         if trigger:
             for section, key, value in uiw:
-                if 'notify_' in section and key == 'type' and 
section.replace('notify_','') in trigger:
+                if 'notify_' in section and key == 'type' and 
section.replace('notify_', '') in trigger:
                     m = getattr(self, value)
                     m(section)

     def fmsnntp(self, config_section):
-        fms_host = self.ui.config(config_section,'fmshost')
-        fms_port = self.ui.config(config_section,'fmsport')
-        fms_user = self.ui.config(config_section,'fmsuser')
-        fms_groups = self.ui.config(config_section,'fmsgroups')
-        updatestatic_template_path = 
self.ui.config(config_section,'updatestatic_message_template')
-        bundle_template_path = 
self.ui.config(config_section,'bundle_message_template')
+        fms_host = self.ui.config(config_section, 'fmshost')
+        fms_port = self.ui.config(config_section, 'fmsport')
+        fms_user = self.ui.config(config_section, 'fmsuser')
+        fms_groups = self.ui.config(config_section, 'fmsgroups')
+        updatestatic_template_path = self.ui.config(config_section, 
'updatestatic_message_template')
+        bundle_template_path = self.ui.config(config_section, 
'bundle_message_template')

         if fms_host and fms_port and fms_user and fms_groups:
             print "Sending notification..."
@@ -214,73 +515,20 @@

             print "NNTP result: %s" % str(result)

-
-
-class myFCP(fcp.FCPNode):
-
-    def putraw(self, id, rawcmd, async=False):
-        """
-        Inserts a raw command.
-        This is intended for testing and development, not for common use
-
-        Arguments:
-            - id - job id, must be the same as identifier in raw command (if 
any)
-            - rawcmd - data passed as is to the node
-            - async - whether to do the job asynchronously, returning a job 
ticket
-              object (default False)
-        """
-
-        opts = {}
-        opts['async'] = async
-        opts['rawcmd'] = rawcmd
-
-        return self._submitCmd(id, "", **opts)
-
-    def putraw2(self, id, rawcmd):
-        """
-        mine ;) verbosity hacking
-        do not print the command
-        """
-
-        self.verbosity = fcp.INFO
-        ticket = self.putraw(id, rawcmd, True)
-        ticket.waitTillReqSent()
-        self.verbosity = fcp.DETAIL
-        return ticket.wait()
-
-    def put_static(self, id, rawcmd):
-        """putraw with status callback method"""
-        opts = dict()
-        opts['async'] = True
-        opts['rawcmd'] = rawcmd
-        opts['callback'] = self.put_status
-
-        ticket = self._submitCmd(id, "", **opts)
-        ticket.wait()
-        return ticket.result
-
-    def put_status(self, status, value):
-        """prints the status messages from jobticket"""
-        if status == 'pending' and value['header'] == 'SimpleProgress':
-            print "Succeeded: %d  -  Required: %d  -  Total: %d  -  Failed: %d 
 -  Final: %s" % (value['Succeeded'], value['Required'], value['Total'], 
value['FatallyFailed'], value['FinalizedTotal'])
-        if status == 'successful':
-            print "inserted successfully: %s" % value
-
-
 class _static_composer(object):
     """
     a helper class to compose the ClientPutComplexDir
     """
     #@    @+others
     #@+node:__init__
-    def __init__(self, repo):
+    def __init__(self, repo, cmd):
         """ """

         self._rootdir = repo.url()[5:] + '/.hg/'
         self._index = 0
         self._fileitemlist = {}
         self._databuff = ''
-        self._cmdbuff = ''
+        self._cmd = cmd
         self._indexname = None

         a = dircache.listdir(self._rootdir)
@@ -301,9 +549,9 @@
         a = dircache.listdir(self._rootdir + dir)
         dircache.annotate(self._rootdir + dir, a)
         for s in a:
-            if s[-1:] == '/':
-                self._parseDir(dir + '/' + s[:-1])
-            elif s[-4:] == 'lock':
+            if s[ - 1:] == '/':
+                self._parseDir(dir + '/' + s[: - 1])
+            elif s[ - 4:] == 'lock':
                 pass # called from hook, ignore
             else:
                 self._addItem(dir, s)
@@ -323,21 +571,21 @@
         self._databuff = self._databuff + content
         idx = str(self._index)

-        self._cmdbuff = self._cmdbuff + "Files."+idx+".Name=.hg/" + virtname + 
'\n'
-        self._cmdbuff = self._cmdbuff + "Files."+idx+".UploadFrom=direct" + 
'\n'
-        self._cmdbuff = self._cmdbuff + 
"Files."+idx+".Metadata.ContentType=text/plain" + '\n'
-        self._cmdbuff = self._cmdbuff + "Files."+idx+".DataLength=" + 
str(len(content)) + '\n'
+        self._cmd.setItem("Files." + idx + ".Name", ".hg/" + virtname)
+        self._cmd.setItem("Files." + idx + ".UploadFrom", "direct")
+        self._cmd.setItem("Files." + idx + ".Metadata.ContentType", 
"text/plain")
+        self._cmd.setItem("Files." + idx + ".DataLength", str(len(content)))

         self._index = self._index + 1

     def addIndex(self, indexpage):
         idx = str(self._index)
-        self._cmdbuff = self._cmdbuff + "Files."+idx+".Name=index.html"+'\n'
-        self._cmdbuff = self._cmdbuff + "Files."+idx+".UploadFrom=direct" + 
'\n'
-        self._cmdbuff = self._cmdbuff + 
"Files."+idx+".Metadata.ContentType=text/html" + '\n'
-        self._cmdbuff = self._cmdbuff + "Files."+idx+".DataLength=" + 
str(len(indexpage)) + '\n'
+        self._cmd.setItem("Files." + idx + ".Name", "index.html")
+        self._cmd.setItem("Files." + idx + ".UploadFrom", "direct")
+        self._cmd.setItem("Files." + idx + ".Metadata.ContentType", 
"text/html")
+        self._cmd.setItem("Files." + idx + ".DataLength", str(len(indexpage)))
         self._index = self._index + 1
-        self._cmdbuff = self._cmdbuff + "DefaultName=index.html\n"
+        self._cmd.setItem("DefaultName", "index.html")

         self._databuff = self._databuff + indexpage

@@ -346,6 +594,9 @@

     def getRawCmd(self):
         return self._cmdbuff + "Data\n" + self._databuff
+    
+    def getData(self):
+        return self._databuff

 # every command must take a ui and and repo as arguments.
 # opts is a dict where you can find other command line flags
@@ -354,17 +605,10 @@
 # don't start with a dash.  If no default value is given in the parameter list,
 # they are required
 def fcp_bundle(ui, repo, **opts):
-    # The doc string below will show up in hg help
     """write bundle to CHK/USK
     the bundel will be inserted as CHK@ if no uri is given
     see hg help bundle for bundle options
     """
-    # setup fcp stuff
-    # set server, port
-    if not opts.get('fcphost'):
-        opts['fcphost'] = ui.config('freenethg', 'fcphost')
-    if not opts.get('fcpport'):
-        opts['fcpport'] = ui.config('freenethg', 'fcpport')

     # make tempfile
     tmpfd, tmpfname = tempfile.mkstemp('fcpbundle')
@@ -382,55 +626,39 @@
     #delete the tempfile again
     os.remove(tmpfname)

-    # now insert the data as chk (first step implementation)
-    #node = fcp.FCPNode(verbosity=fcp.DETAIL)
-    node = _make_node(**opts)
-
     print "insert now. this may take a while..."
+  
+    try:
+        conn = HgFCPConnection(ui, **opts)
+        resulturi = hgBundlePut(conn, bundledata)
+    except Exception, e:
+        print e
+        return

-    insertresult = node.put(data=bundledata, priority=1, 
mimetype="mercurial/bundle", async=True, callback=node.put_status)
-    insertresult.wait()
-
-    node.shutdown()
-
-    if insertresult:
-
-        notify_data = {'uri' : insertresult,
+    notify_data = {'uri' : resulturi,
                        'type' : 'bundle',
-                       'repository' : '%s' % repo.root.split('/')[-1],
+                       'repository' : '%s' % repo.root.split('/')[ - 1],
                        'base' : opts.get('base'),
                        'rev' : opts.get('rev')}

-        notifier = Notifier(ui, notify_data, autorun=True)
+    notifier = Notifier(ui, notify_data, autorun=True)

-
-
 def fcp_unbundle(ui, repo, uri , **opts):
-    # The doc string below will show up in hg help
     """unbundle from CHK/USK"""

-    # set server, port
-    if not opts.get('fcphost'):
-        opts['fcphost'] = ui.config('freenethg', 'fcphost')
-    if not opts.get('fcpport'):
-        opts['fcpport'] = ui.config('freenethg', 'fcpport')
-
     # make tempfile
     tmpfd, tmpfname = tempfile.mkstemp('fcpbundle')

-    node = _make_node(**opts)
-
     unbundle = None

     try:
-        unbundle = node.get(uri, priority=1, maxretries=5)
-    except fcp.node.FCPException, e:
+        conn = HgFCPConnection(ui, **opts)
+        unbundle = hgBundleGet(conn, uri)
+    except Exception, e:
         print e

-    node.shutdown()
-
     if unbundle:
-        changes = unbundle[1]
+        changes = unbundle
         f = open(tmpfname, 'wb')
         f.write(changes)
         f.close()
@@ -438,62 +666,6 @@

     os.remove(tmpfname)

-def _make_node(**opts):
-    fcpopts = {}
-    fcpopts['verbosity'] = fcp.INFO
-    host = opts.get('fcphost', None)
-    if host:
-        fcpopts['host'] = host
-    port = opts.get('fcpport', None)
-    if port:
-        fcpopts['port'] = port
-    #return node2.FCPNode(**fcpopts)
-    return myFCP(**fcpopts)
-
-def fcp_makestatic(ui, repo, uri=None, **opts):
-    """put the repo into freenet for access via static-http
-    """
-
-    id = "freenethgid" + str(int(time.time() * 1000000))
-
-    config_uri = ui.config('freenethg', 'inserturi')
-
-    if uri == None:
-        if config_uri:
-            uri = config_uri
-        else:
-            uri="CHK@"
-
-    if not opts.get('fcphost'):
-        opts['fcphost'] = ui.config('freenethg', 'fcphost')
-    if not opts.get('fcpport'):
-        opts['fcpport'] = ui.config('freenethg', 'fcpport')
-    cmd = "ClientPutComplexDir\n" + "URI=" + uri + "\nIdentifier=" + id
-    cmd = cmd + 
"\nVerbosity=-1\nPriorityClass=1\nMaxRetries=5\nDontCompress=true\n"
-
-    composer = _static_composer(repo)
-
-    print "Debug: " + cmd + composer.getCmd()
-
-    print "site composer done."
-    print "insert now. this may take a while..."
-
-    node = _make_node(**opts)
-
-    testresult = None
-
-    try:
-        #testresult = node.putraw(id, cmd + composer.getRawCmd())
-        testresult = node.put_static(id, cmd + composer.getRawCmd())
-    except fcp.node.FCPException, e:
-        print e
-
-    node.shutdown()
-
-#    if testresult:
-#        print "success: " + testresult
-        # here method for automated fms posts should be called
-
 def fcp_createstatic(ui, repo, uri=None, **opts):
     """put the repo into freenet for access via static-http, updatedable (not 
implemented jet)
     """
@@ -501,56 +673,76 @@
     pass

 def fcp_updatestatic(ui, repo, **opts):
-    """update the repo in freenet for access via static-http
-    """
+    """update the repo in freenet for access via static-http"""

     updatestatic_hook(ui, repo, None, **opts)

 def updatestatic_hook(ui, repo, hooktype, node=None, source=None, **kwargs):
     """update static """

-
     id = "freenethgid" + str(int(time.time() * 1000000))
-    host = ui.config('freenethg', 'fcphost')
-    port = ui.config('freenethg', 'fcpport')
+    
+    if not kwargs.get('fcphost'):
+        host = ui.config('freenethg', 'fcphost')
+    else:
+        host = kwargs.get('fcphost')
+        
+    if not kwargs.get('fcpport'):
+        port = ui.config('freenethg', 'fcpport')
+    else:
+        port = kwargs.get('fcpport')

-    uri = ui.config('freenethg', 'inserturi')
+    if not kwargs.get('uri'):
+        uri = ui.config('freenethg', 'inserturi')
+    else:
+        uri = kwargs.get('uri')

-    fcpopts = {}
-    fcpopts['verbosity'] = fcp.INFO
-    fcpopts['host'] = host
-    fcpopts['port'] = port
-
-    #fcpopts['logfunc'] = ui.log
-    node = myFCP(**fcpopts)
-
-    cmd = "ClientPutComplexDir\n" + "URI=" + uri + "\nIdentifier=" + id
-    cmd = cmd + 
"\nVerbosity=-1\nPriorityClass=1\nMaxRetries=5\nDontCompress=true\n"
-
-    composer = _static_composer(repo)
+    cmd = FCPCommand("ClientPutComplexDir")
+    cmd.setItem('Verbosity', -1)
+    cmd.setItem('URI', uri)
+    cmd.setItem('MaxRetries', -1)
+    cmd.setItem('DontCompress', 'false')
+    cmd.setItem('PriorityClass', '1')
+    
+    composer = _static_composer(repo, cmd)
     page_maker = IndexPageMaker()
     indexpage = page_maker.get_index_page(ui)
     composer.addIndex(indexpage)

-    print "Debug: " + cmd + composer.getCmd()
-
     print "site composer done."
     print "insert now. this may take a while..."

     result = None

     try:
-        result = node.put_static(id, cmd + composer.getRawCmd())
-    except fcp.node.FCPException, e:
-        print e
+        conn = HgFCPConnection(ui, **kwargs)
+        conn.sendCommand(cmd, composer.getData())
+    
+        while True:
+            msg = conn.readEndMessage()
+        
+            if msg.isMessageName('PutSuccessful'):
+                return msg.getValue('URI')
+        
+            if msg.isMessageName('ProtocolError'):
+                raise Exception("ProtocolError(%d) - %s: %s" % 
(msg.getIntValue('Code'), msg.getValue('CodeDescription'), 
msg.getValue('ExtraDescription')))
+            
+            if msg.isMessageName('PutFailed'):
+                raise Exception("This should really not happen!")
+        
+            if msg.isMessageName('SimpleProgress'):
+                print "Succeeded: %d  -  Required: %d  -  Total: %d  -  
Failed: %d  -  Final: %s" % (msg.getIntValue('Succeeded'), 
msg.getIntValue('Required'), msg.getIntValue('Total'), 
msg.getIntValue('FatallyFailed'), msg.getValue('FinalizedTotal'))
+                continue

-    node.shutdown()
+            print msg.getMessageName()

+    except Exception, e:
+        print e
+        return
+    
     if result:
-
         notify_data = {'uri' : result,
                        'type' : 'updatestatic'}
-
         notifier = Notifier(ui, notify_data, autorun=True)


@@ -621,8 +813,9 @@
 ]

 fcpopts = [
-    ('', 'fcphost', None, 'specify fcphost if not 127.0.0.1'),
-    ('', 'fcpport', None, 'specify fcpport if not 9481'),
+    ('', 'fcphost', '', 'specify fcphost if not 127.0.0.1'),
+    ('', 'fcpport', 0, 'specify fcpport if not 9481'),
+    ('', 'fcptimeout', 0, 'specify fcp timeout if not 5 minutes'),
 ]

 cmdtable = {
@@ -631,22 +824,16 @@
                       [('f', 'force', None, 'run even when remote repository 
is unrelated'),
                        ('r', 'rev', [], 'a changeset you would like to 
bundle'),
                        ('', 'base', [], 'a base changeset to specify instead 
of a destination'),
+                       ('a', 'all', None, 'bundle all changesets in the 
repository'),
                        ('', 'uri', None, 'use insert uri generate chk'),
-                      ]+ remoteopts + fcpopts,
+                      ] + remoteopts + fcpopts,
                       'hg fcp-bundle [--uri INSERTURI] [-f] [-r REV]... 
[--base REV]... [DEST]'),
        "fcp-unbundle": (fcp_unbundle,
                         [('u', 'update', None, 'update to new tip if 
changesets were unbundled'),
                          ] + fcpopts,
                         'hg fcp-unbundle [-u] FREENETKEY'),
-       "fcp-makestatic": (fcp_makestatic,
-                        [('', 'uri', None, 'use insert uri instead generate 
chk')
+       "fcp-updatestatic": (fcp_updatestatic,
+                        [('', 'uri', '', 'use insert uri instead from hgrc')
                          ] + fcpopts,
-                        'hg fcp-makestatic [INSERTURI]'),
-       #"fcp-createstatic": (fcp_createstatic,
-       #                 [('a', 'auto', None, 'install update hook'),
-       #                  ] + fcpopts,
-       #                 'hg fcp-createstatic'),  
-       "fcp-updatestatic": (fcp_updatestatic,
-                        [] + fcpopts,
-                        'hg fcp-updatestatic')
+                        'hg fcp-updatestatic [--uri INSERTURI]')
 }

Modified: trunk/apps/pyFreenetHg/ReadMe.html
===================================================================
--- trunk/apps/pyFreenetHg/ReadMe.html  2008-11-26 18:05:32 UTC (rev 23894)
+++ trunk/apps/pyFreenetHg/ReadMe.html  2008-11-26 22:37:17 UTC (rev 23895)
@@ -21,7 +21,6 @@
 the basic idea: wrap around (selected) commands and use freenet as transport 
instead files
      hg fcp-bundle   -> wraps around hg bundle and put a chk/usk instead a 
local file
      hg fcp-unbundle -> wraps around hg unbundle and get it from a chk/usk 
instead a local file        
-     hg fcp-makestatic (not yet) -> create a site thats accessible via 
static-http://127.0.0.1:8888/freenetkey
      hg fcp-updatestatic -> do a commit hook upload, useful if the insert 
started from commit hook was failed

 hooks:
@@ -35,7 +34,6 @@
 <p>
 python &gt;= 2.4<br>
 mercurial &gt;= 1.x<br>
-pyFCP<br>
 last not least: a running freenet node ;)<br />
 optional: <a href="/USK at 
MYLAnId-ZEyXhDGGbYOa1gOtkZZrFNTXjFl1dibLj9E,Xpu27DoAKKc8b0718E-ZteFrGqCYROe7XBBJI57pB4M,AQACAAE/SiteToolPlugin/0/"
 target="_blank">SiteToolPlugin</a>
 </p>


Reply via email to