You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
9.8 KiB

  1. import configparser
  2. import getopt
  3. import os
  4. import sys
  5. from ftplib import FTP, error_perm
  6. import git
  7. class GitUtil(object):
  8. user = None
  9. passwd = None
  10. git_url = None
  11. dir_name = None
  12. repo = git.Repo
  13. def __init__(self, **kwargs):
  14. user = kwargs.pop("user")
  15. passwd = kwargs.pop("passwd")
  16. git_url = kwargs.pop("git_url")
  17. if passwd and user and git_url:
  18. self.passwd = passwd
  19. self.user = user
  20. git_url = str(git_url).replace("http://", "")
  21. self.dir_name = git_url.split("/")[-1].split(".")[0]
  22. self.git_url = git_url
  23. else:
  24. raise Exception("(user,passwd,git_url)必须全部传")
  25. self.__user_login()
  26. def __user_login(self):
  27. temp_dir = os.getenv('TEMP') + "/" + self.dir_name
  28. if os.path.exists(temp_dir + "/" + ".git"):
  29. self.repo = git.Repo.init(temp_dir)
  30. # 强制更新最新代码 覆盖本地的
  31. self.repo.git.execute('git reset --hard origin/master')
  32. print("git目录已经存在!")
  33. return
  34. try:
  35. self.repo = git.Repo.clone_from("http://%s:%s@%s" % (self.user, self.passwd, self.git_url),
  36. to_path=temp_dir)
  37. print("克隆成功!")
  38. except Exception as e:
  39. raise Exception("克隆出错:%s" % e.args)
  40. def get_diff_file(self, old_version):
  41. new_version = self.get_current_version()
  42. resp = self.repo.git.execute("git diff -no-pager --name-only %s %s" % (old_version, new_version))
  43. if len(resp) is 0:
  44. return None
  45. return resp.split("\n")
  46. def get_current_version(self):
  47. return self.repo.head.log_entry(-1).newhexsha
  48. class FtpUtil(object):
  49. ftp = FTP()
  50. log = ""
  51. list_name = []
  52. dict_dir = {}
  53. cur_dir = ""
  54. def __init__(self, host, user, pwd, port=21):
  55. self.ftp.connect(host=host, port=port)
  56. self.ftp.login(user=user, passwd=pwd)
  57. self.ftp.set_pasv(False)
  58. def get_remote_name(self, line):
  59. file_name = str(line).split(" ")[-1]
  60. if file_name not in [".", ".."]:
  61. type_file = line[0]
  62. self.dict_dir[self.cur_dir].append([type_file, file_name])
  63. def remote_local_same(self, remote_path, local_path):
  64. try:
  65. remote_size = self.ftp.size(remote_path)
  66. except Exception as e:
  67. remote_size = -1
  68. try:
  69. local_size = os.path.getsize(local_path)
  70. except Exception as e:
  71. local_size = -1
  72. print("ftp目录的文件【%s】大小为【%s" % (remote_path, remote_size))
  73. print("本地目录的文件【%s】大小为【%s" % (local_path, local_size))
  74. print("------------------------------------")
  75. if remote_size == local_size:
  76. return 1
  77. else:
  78. return 0
  79. def down_file(self, remote_path, local_path):
  80. if not self.remote_local_same(remote_path, local_path):
  81. if not os.path.exists(os.path.dirname(local_path)):
  82. os.makedirs(os.path.dirname(local_path))
  83. local_fp = open(local_path, 'wb')
  84. self.ftp.retrbinary("RETR " + remote_path, local_fp.write)
  85. local_fp.close()
  86. def down_files(self, remote_path, local_path):
  87. try:
  88. self.ftp.cwd(remote_path)
  89. except error_perm as e:
  90. return
  91. print("------------------------------------")
  92. print("ftp目录切换到:%s" % self.ftp.pwd())
  93. try:
  94. self.cur_dir = self.ftp.pwd()
  95. self.dict_dir[self.cur_dir] = []
  96. self.ftp.dir(self.get_remote_name)
  97. for i in self.dict_dir[self.ftp.pwd()]:
  98. local_ = os.path.join(local_path, i[1])
  99. if i[0] == "-":
  100. self.down_file(i[1], local_)
  101. elif i[0] == "d":
  102. self.down_files(i[1], local_)
  103. self.ftp.cwd('..')
  104. except Exception as e:
  105. print("超时ing......。正在重新连接!")
  106. self.down_files("./", "./")
  107. self.list_name = []
  108. self.dict_dir = {}
  109. self.cur_dir = ""
  110. print("回到目录【%s" % self.ftp.pwd())
  111. print("------------------------------------")
  112. def read_version_file(self):
  113. self.ftp.cwd("/")
  114. fp = open("./.version", "wb")
  115. try:
  116. self.ftp.retrbinary("RETR .version", fp.write)
  117. except error_perm as e:
  118. if "550" in e.__str__():
  119. return 0
  120. finally:
  121. fp.close()
  122. if os.path.getsize("./.version") == 0:
  123. return 0
  124. return 1
  125. def upload_file(self, local_path, remote_path):
  126. print("-----------------------")
  127. print("即将上传的文件为:【%s" % local_path)
  128. self.ftp.cwd("/")
  129. fp = open(local_path, "rb")
  130. buf_size = 1024
  131. try:
  132. self.ftp.storbinary("STOR %s" % remote_path, fp, buf_size)
  133. print("文件为:【%s" % local_path, "已经上传成功!")
  134. except error_perm as e:
  135. print("出错文件:【%s" % remote_path + "\r\n", "出错原因:【%s" % e.args)
  136. finally:
  137. fp.close()
  138. print("-------------------------------------")
  139. def init_config():
  140. try:
  141. opts, args = getopt.getopt(sys.argv[1:], "hf:", ["file="])
  142. if not opts:
  143. if os.path.exists("./.ftp_git.ini"):
  144. opts = [('-f', ".ftp_git.ini")]
  145. except getopt.GetoptError:
  146. print(sys.argv[0] + ' -f 配置文件路径')
  147. sys.exit(2)
  148. for opt, arg in opts:
  149. if opt in ("-h", "--help"):
  150. print(sys.argv[0] + ' -f 配置文件路径')
  151. print("""
  152. [ftp]
  153. user =
  154. passwd =
  155. host = ip地址
  156. port = 21
  157. [git]
  158. user =
  159. passwd =
  160. url =
  161. """)
  162. sys.exit()
  163. elif opt in ("-f", "--file"):
  164. cf = configparser.ConfigParser()
  165. try:
  166. cf.read(arg, encoding='gbk')
  167. ftp_user = cf.get("ftp", "user")
  168. ftp_passwd = cf.get("ftp", "passwd")
  169. host = cf.get("ftp", "host")
  170. port = cf.get("ftp", "port")
  171. git_user = cf.get("git", "user")
  172. git_passwd = cf.get("git", "passwd")
  173. url = cf.get("git", "url")
  174. except configparser.NoSectionError as s:
  175. print("请在配置文件中配置:[%s]节点" % s.section)
  176. sys.exit()
  177. except configparser.NoOptionError as e:
  178. print("请在[%s]节点中配置:%s 选项" % (e.section, e.option))
  179. sys.exit()
  180. if not opts:
  181. print("开始配置ftp信息")
  182. ftp_user = input("请输入ftp登录账号:")
  183. while not ftp_user:
  184. ftp_user = input("ftp登录账号不能为空(重新输入):")
  185. ftp_passwd = input("请输入ftp登录密码:")
  186. while not ftp_passwd:
  187. ftp_passwd = input("ftp登录密码不能为空(重新输入):")
  188. host = input("请输入ftp的连接ip地址:")
  189. if not host:
  190. host = input("ftp的连接ip地址不能为空(重新输入):")
  191. port = input("请输入ftp连接的端口号地址(默认21):")
  192. if not port:
  193. port = "21"
  194. print("开始配置git信息")
  195. git_user = input("请输入git的对应地址仓库需要的用户名:")
  196. while not git_user:
  197. git_user = input("git的对应地址仓库需要的用户名不能为空(重新输入):")
  198. git_passwd = input("请输入git的对应地址仓库需要的密码:")
  199. if not git_passwd:
  200. git_passwd = input("git的对应地址仓库需要的密码不能为空(重新输入):")
  201. url = input("请输入git的对应地址:")
  202. if not url:
  203. url = input("git的对应地址不能为空(重新输入):")
  204. cf = configparser.ConfigParser()
  205. cf.add_section("ftp")
  206. cf.add_section("git")
  207. cf.set("ftp", "host", host)
  208. cf.set("ftp", "passwd", ftp_passwd)
  209. cf.set("ftp", "user", ftp_user)
  210. cf.set("ftp", "port", port)
  211. cf.set("git", "user", git_user)
  212. cf.set("git", "passwd", git_passwd)
  213. cf.set("git", "url", url)
  214. with open(file="./.ftp_git.ini", mode="w") as f:
  215. cf.write(f)
  216. return host, port, ftp_user, ftp_passwd, url, git_user, git_passwd
  217. if __name__ == "__main__":
  218. """
  219. """
  220. host, port, ftp_user, ftp_passwd, url, git_user, git_passwd = init_config()
  221. git_util = GitUtil(user=git_user, git_url=url, passwd=git_passwd, port=port)
  222. ftp_util = FtpUtil(host, ftp_user, ftp_passwd)
  223. code = ftp_util.read_version_file()
  224. file_dir_local = os.getenv('TEMP') + "/" + git_util.dir_name
  225. if code == 1:
  226. with open(".version", "r") as r:
  227. line = r.read()
  228. # 获取到不同的文件路径
  229. file_paths = git_util.get_diff_file(line)
  230. if file_paths is None:
  231. print("本地文件和线上对比:文件无变化!")
  232. else:
  233. for file in file_paths:
  234. ftp_util.upload_file(file_dir_local + "/" + file, file)
  235. else:
  236. # 如果不存在版本记录文件。那就全部覆盖
  237. for root, dirs, files in os.walk(file_dir_local):
  238. for name in files:
  239. if ".git" not in root:
  240. ftp_util.upload_file("/".join((root, name)), name)
  241. # 最后都要用最新的版本记录覆盖线上的版本记录文件
  242. cur_version = git_util.get_current_version()
  243. with open(".version", "w") as w:
  244. w.write(cur_version)
  245. ftp_util.upload_file(".version", ".version")
  246. print("已经完成覆盖!当前版本为:%s" % cur_version)