Guest User

Ftp uploader

a guest
Sep 1st, 2010
196
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # -*- coding: cp1251 -*-
  2. import logging
  3. from subprocess import Popen, PIPE
  4. from time import sleep
  5.  
  6. def main():
  7.     logging.getLogger('MyLogger').debug('main app started')
  8.     usage = """usage: %prog -c PATH -r REVISION --host user@host -d start_dir -p password
  9. Use to upload website from repository
  10. """
  11.     from optparse import OptionParser
  12.     parser = OptionParser(usage=usage)
  13.     parser.add_option("-c", "--copy", dest="copy", action = "store",
  14.                       help = "PATH of local working copy", type="string")
  15.     parser.add_option("--host", dest="host",
  16.                       help = "host to connect to", type="string")
  17.     parser.add_option("-r", "--revision", dest="revision",
  18.                       help = "override revision number from which to update sources", type="string")
  19.     parser.add_option("-p", "--password", dest="password",
  20.                       help = "password to use when connecting to ftp", type="string")
  21.     parser.add_option("-d", "--directory", dest="directory",
  22.                       help = "directory, relative to ftp root, in which project lies", type="string")
  23.     (options, args) = parser.parse_args()
  24.    
  25.     if None == options.copy:
  26.         print("-c option is required")
  27.         logging.getLogger('MyLogger').info('omitted -c option')
  28.         return 2
  29.     if None == options.host:
  30.         print("--host option is required")
  31.         logging.getLogger('MyLogger').info('omitted --host option')
  32.         return 2
  33.     if None == options.directory:
  34.         print("-d option is required")
  35.         logging.getLogger('MyLogger').info('omitted -d option')
  36.         return 2
  37.     if "/" == options.directory:
  38.         print("root dir is not allowed!")
  39.         logging.getLogger('MyLogger').warning('trying access root / dir is not allowed, please use subfolders')
  40.         return 2
  41.     tmp = {'copy': options.copy, 'revision': options.revision, 'host': options.host, 'directory': options.directory}
  42.     logging.getLogger('MyLogger').debug('called with these options: '+' '.join('-%s %s' % (k, v) for k, v in tmp.items()))
  43.     # here I MUST check if network is reachable
  44.     port = 21
  45.     username, host = options.host.split('@',1)
  46.     if False == is_server_reachable(host, port): #checking FTP port 21
  47.       print('ftp service on specified host is not available')
  48.       logging.getLogger('MyLogger').critical('host '+options.host+':'+str(port)+' was unreachable')
  49.       return 1
  50.     base_revision = 0
  51.     head_revision = 0
  52.     url = ''
  53.     path  = options.copy#'C:\Program Files\CruiseControl\projects\email_sender_server\source'
  54.     # here I must take revision number into consideration
  55.     if None == options.revision:
  56.       cmd = 'svn info -r BASE "' + path + '"'
  57.       logging.getLogger('MyLogger').debug(cmd)
  58.       svn = Popen(cmd, stdout = PIPE)
  59.       i = 0
  60.       for line in svn.stdout.readlines():
  61.         i = i + 1
  62.         if i < 9:
  63.           l = line[:-2].decode('cp1251').split(': ',1)
  64.           if l[0] == 'Revision': base_revision = l[1]
  65.       svn.wait()
  66.     else:
  67.       base_revision = options.revision      
  68.     cmd = 'svn info -r HEAD "' + path + '"'
  69.     logging.getLogger('MyLogger').debug(cmd)      
  70.     svn = Popen(cmd, stdout = PIPE)
  71.     i = 0
  72.     for line in svn.stdout.readlines():
  73.       i = i + 1
  74.       if i < 9:
  75.         l = line[:-2].decode('cp1251').split(': ',1)
  76.         if l[0] == 'Revision': head_revision = l[1]
  77.         if l[0] == 'URL': url = l[1]        
  78.     info = {'head': head_revision, 'base': base_revision, 'url': url}
  79.     svn.wait()    
  80.     cmd = "svn diff --summarize -r"+info['base']+":"+info['head']+' "'+info['url'] + '"'
  81.     logging.getLogger('MyLogger').debug(cmd)
  82.     svn = Popen(cmd, stdout = PIPE)
  83.     commands = []
  84.     f = open("C:\\scenario.txt", "w")
  85.     for line in svn.stdout.readlines():
  86.       l = line.decode('866')[:-1]
  87.       action = l[0:7].strip()
  88.       source = l[7:]
  89.       if source == info['url']:
  90.         continue
  91.       commands.append((action,source))
  92.       f.write(action + "," + source)
  93.     f.close()
  94.     svn.wait()
  95.    
  96.     logging.getLogger('MyLogger').debug('updating local working copy')
  97.     cmd = 'svn up "'+path+'"'
  98.     logging.getLogger('MyLogger').debug(cmd)
  99.     logging.getLogger('MyLogger').debug('at revision '+head_revision)
  100.     svn = Popen(cmd)
  101.     svn.wait()
  102.     import os
  103.     cmd = []
  104.     for line in commands:
  105.       action,source = line
  106.       #logging.getLogger('MyLogger').info('source: '+source.strip()+' action: '+action+' url:'+info['url'])
  107.       if source.strip() == info['url'].strip():
  108.         print(source)        
  109.         continue
  110.       onserver = source.replace(info['url'] + "/", "").strip()
  111.       action = action[0:1]
  112.       if action == 'D':
  113.         c = 'rm -rf "./'+onserver + '"'
  114.         if c not in cmd:
  115.           cmd.append(c)
  116.         c = 'rm -f "./'+onserver + '"'          
  117.         if c not in cmd:
  118.           cmd.append(c)
  119.       else:
  120.         dirs_to_cr = onserver.split('/')
  121.         if os.path.isdir(path + "\\" + onserver):
  122.           c = 'mkdir -p "./'+"/".join(dirs_to_cr[j] for j in range(0,len(dirs_to_cr)))+'"'
  123.           if c not in cmd:
  124.             cmd.append(c)
  125.         else:
  126.           if 1 < len(dirs_to_cr):
  127.             c = 'mkdir -p "./'+"/".join(dirs_to_cr[j] for j in range(0,len(dirs_to_cr)-1))+'"'
  128.             if c not in cmd:  
  129.               cmd.append(c)
  130.           c = 'put "/cygdrive/' + path[0:1] + path[2:].replace("\\", '/') + '/' + onserver + '" -o "./' + onserver + '"'
  131.           if c not in cmd:
  132.             cmd.append(c)
  133.     if 0 == len(cmd):
  134.       print("I got nothing to do this time :(")
  135.       logging.getLogger('MyLogger').info('nothing to do')
  136.     else:
  137.       cmd.insert(0, 'open -u '+username+','+options.password+' '+host)
  138.       cmd.insert(1, 'cd '+options.directory)
  139.       cmd.append("exit")
  140.       from tempfile import mkdtemp
  141.       tmpdir = mkdtemp()
  142.       tmpscenario = tmpdir+"/ftp_scenario.txt"
  143.       f = open(tmpscenario, "wb")
  144.       for c in cmd:
  145.         logging.getLogger('MyLogger').info('lftp: ' + c)
  146.         f.write(bytes(c + chr(10),'cp1251'))
  147.       f.close()
  148.       logging.getLogger('MyLogger').debug('logging in to ftp')
  149.       ftp = get_ftp(tmpscenario)
  150.       logging.getLogger('MyLogger').info('communicating')
  151.       ftp.communicate()
  152.       logging.getLogger('MyLogger').info('finished communicating')
  153.       ftp.wait()    
  154.       import os
  155.       os.remove(tmpscenario)
  156.       os.rmdir(tmpdir)
  157.     logging.getLogger('MyLogger').debug('main application finished')      
  158.     return 0
  159.    
  160. def get_ftp(script):
  161.   cmd = 'C:/lftp/lftp.exe -f "'+windows_path_to_cygpath(script)+'"'
  162.   logging.getLogger('MyLogger').debug(cmd)
  163.   ftp = Popen(cmd)
  164.   #ftp.stdin.write(bytes(cmd+"\n", 'cp1251'))
  165.   return ftp
  166.  
  167. def is_server_reachable(hostname, port):
  168.   import socket
  169.   sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  170.   try:
  171.     sock.connect((hostname, port))
  172.   except socket.error:
  173.     return False    
  174.   sock.close()
  175.   return True  
  176.  
  177. def windows_path_to_cygpath(winpath):
  178.   return '/cygdrive/' + winpath[0:1] + winpath[2:].replace("\\", '/')
RAW Paste Data