背景
公司制品庫遷移,要將npm庫從原制品庫nexus遷移到artifactory中。涉及到近千的依賴包,手動太過費時。因此通過python腳本進行批量操作
思路
梳理思路,單個包的遷移步驟如下:下載包->修改包(package.json)中倉庫地址->執行npm publish命令。
與單個包相比,批量操作還需要能拿到包的所有下載地址,在推送之前需要登錄npm并設置全局repository地址。
獲取包的下載地址
倉庫包組件不多,但版本多。因此我選擇直接在瀏覽器中console通過js腳本獲取url,如果組件較多建議寫腳本獲取。
// 將數據以文件形式存儲
(function (console) {
console.save = function (data, filename) {
if (!data) {
console.error('Console.save: No data')
return;
}
if (!filename) filename = 'console.json'
if (typeof data === "object") {
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], { type: 'text/json' }),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
})(console)
//獲取a標簽中url
function getHref(a){
var urlArr = new Array();
var hrefArr = document.getElementsByTagName('a'); //獲取這個頁面的所有A標簽
for( var i=0; i<hrefArr.length; i++ ){
hrefURL = hrefArr[i].href;
urlArr[i] = hrefURL;
}
console.save(urlArr,a);
}
//執行獲取腳本
getHref("XXXX.txt");
獲取到的url文件(XXXX.txt)如下:
[
"http://xxxx.com/service/rest/repository/browse/npm/xxxx/",
"http://xxxx.com/repository/npm/xxxx/xxxx.tgz"
]
python 腳本
目錄
tmp_package
tmp_tar_package
tmp_utar_package
urls
auto.py
replace_file.py
tmp_package、tmp_tar_package、tmp_utar_package目錄為空目錄,urls中存放上一部中獲取的url文件;
代碼
- replace_file.py
def replace_content(file,old_content,new_content):
content=read_file(file)
content=content.replace(old_content,new_content)
rewrite_file(file,content)
#讀文件
def read_file(file):
with open(file,encoding='UTF-8') as f:
read_all = f.read()
f.close()
return read_all
#寫內容到文件
def rewrite_file(file,data):
with open(file,'w',encoding='UTF-8') as f:
f.write(data)
f.close()
- auto.py,運行腳本前需要登錄有權限的npm賬號
import wget
import os
import shutil
import tarfile
import replace_file
import urllib.parse
path='tmp_package/'
utar_path='tmp_utar_package/'
tar_path='tmp_tar_package/'
def tzgName(url):
#根據url獲取壓縮包名稱
arr=url.split('-/')
return arr[1]
def readPackageUrls(f):
#從文件中讀取地址
urls = []
f = 'urls/'+f
file=open(f)
data_lists=file.readlines()
for i in data_lists:
if i.rfind('.tgz') != -1:
urls.append(i.replace('"','').replace(',\n',''))
return urls
def dowanloadPackages(urls):
#下載文件
for u in urls:
u=u.strip()
u=urllib.parse.unquote(u)
name = path + tzgName(u)
print(u)
print(name)
t=wget.download(u,name)
return 'download success! size: '
def utar():
#文件解壓
for f in os.listdir(path):
dest_dir=f.replace('.tgz','')
dest_dir=utar_path+dest_dir
f=path+f
try:
tar=tarfile.open(f)
names=tar.getnames()
for name in names:
tar.extract(name,dest_dir)
tar.close()
except Exception as e:
print(e)
def ptar():
#這個沒用
for f in os.listdir(utar_path):
tar = tar_path+f+'.tgz'
f=utar_path+f+'/package/'
try:
with tarfile.open(tar,'w:gz') as tar:
tar.add(f,arcname=os.path.basename(f))
except Exception as e:
print(e)
def repalce():
#這一步把需要替換的文件中字符串替換掉,主要是倉庫地址
old_path='http://xxxx.com/repository/npm/'
old_path1='http://xxxx.cn/repository/npm/'
new_path='https://xxxx.com/artifactory/api/npm/npm-releases/'
for f in os.listdir(utar_path):
package_path= utar_path + f + '/package/package.json'
replace_file.replace_content(package_path,old_path,new_path)
replace_file.replace_content(package_path,old_path1,new_path)
def dealPackage():
utar()
repalce()
# ptar()
return 'deal package success!'
def pushPackage():
for i in os.listdir(utar_path):
p = utar_path+i+'/package/'
shell= 'cd ' + p + ' & npm publish & cd ../../../'
print(shell)
os.system(shell)
return 'publish package success!'
def cleanTmp():
shutil.rmtree(path)
shutil.rmtree(utar_path)
shutil.rmtree(tar_path)
os.makedirs(path)
os.makedirs(utar_path)
os.makedirs(tar_path)
cleanTmp()
sum = 0
for f in os.listdir('urls'):
us = readPackageUrls(f)
cleanTmp()
dowan=dowanloadPackages(us)
deal=dealPackage()
push=pushPackage()
print('處理文件:%s,共:%d條數據'%(f,len(us)))
sum+=len(us)
print('共處理文件:%d 條數據'%(sum))