完整的代码, 可以复制引用
//导入必要的模块
const fs = require('fs')
const exec = require('child_process').exec
// 配置相关的路径
// 打包后的git本地仓库的路径
const cwd = '/Users/ff/Desktop/git1/h5_build'
// 需要复制的目录路径
const cwd2 = '/Users/ff/Desktop/git2/web/unpackage/dist/build/h5'
// 允许被复制的文件后缀列表
const copyExt = ['.html', '.php']
// 定义复制文件夹的函数
/**
* 复制一个文件夹下的文件到另一个文件夹
* @param src 源文件夹
* @param dst 目标文件夹
*/
let copyDir = null;
exec('git fetch --all', { cwd }, function (error, stdout, stderr) {
if (error) {
return false;
}
exec('git reset --hard origin/dev', { cwd }, function (error, stdout, stderr) {
if (error) {
return false;
}
exec('git pull origin dev', { cwd }, function (error, stdout, stderr) {
if (error) {
return false;
}
console.log(`git pull 成功`)
copyDir = function (src, dst) {
// 读取目录中的所有文件/目录
fs.readdir(src, function (err, paths) {
if (err) {
throw err
}
emptyDir(dst)
paths.forEach(function (path) {
const _src = src + '/' + path
const _dst = dst + '/' + path
let readable
let writable
fs.stat(_src, function (err, st) {
if (err) {
throw err
}
// 判断是否为文件
if (st.isFile()) {
// 允许的后缀才可以被复制
// if (contains(copyExt, _src)) {
// // 创建读取流
// readable = fs.createReadStream(_src)
// // 创建写入流
// writable = fs.createWriteStream(_dst)
// // 通过管道来传输流
// readable.pipe(writable)
// } else {
//
// // console.log(_src + ' 不允许被复制!!!')
// }
setTimeout(() => {
// 创建读取流
readable = fs.createReadStream(_src)
// 创建写入流
writable = fs.createWriteStream(_dst)
// 通过管道来传输流
readable.pipe(writable)
}, 600)
}
// 如果是目录则递归调用自身
else if (st.isDirectory()) {
exists(_src, _dst, copyDir)
}
})
})
})
}
exists(cwd2, cwd, copyDir)
setTimeout(() => {
autoGit();
}, 3000)
})
})
})
// 执行提交git
function autoGit () {
// 无需提交
let noCommitFlag = false;
exec('git add .', { cwd }, function (error, stdout, stderr) {
if (error) {
console.log(stdout)
console.log(`git add 失败${stderr}`)
errIndexLock(stderr)
return false
}
console.log(`git add 成功`)
exec('git commit -am "自动提交成功"', { cwd }, function (error, stdout, stderr) {
if (error) {
console.log(stdout)
errCommit(stdout)
errIndexLock(stderr)
if (noCommitFlag) {
console.log(`本地git没有任何更新`)
return false
}
}
console.log(`git commit 成功`)
exec('git push origin dev', { cwd }, function (error, stdout, stderr) {
if (error) {
console.log(stdout)
console.log(`git push 失败 ${stderr}`)
errIndexLock(stderr)
}
console.log(`git push 成功`)
})
})
})
// 很干净 无需commit
function errCommit(stdout) {
if(stdout.indexOf('nothing to commit') > -1) {
noCommitFlag = true;
}
}
// 删除文件 路径 解决提交报index.lock存在的错误
function errIndexLock(stderr) {
fs.exists(cwd + '/.git/index.lock', function(exists) {
if(exists && stderr.indexOf('index.lock')) {
fs.unlink(cwd + '/.git/index.lock',err=>{
if(err) return console.log(err)
})
setTimeout(() => {
autoGit()
}, 500)
}
});
}
}
/**
* 删除指定路径下的所有文件
*/
function emptyDir(path) {
const files = fs.readdirSync(path)
// 过滤不删除的文件
let noDelete = ['.git', 'README.md', 'pc.html']
files.forEach(file => {
if (!noDelete.includes(file)) {
const filePath = `${path}/${file}`;
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
emptyDir(filePath);
} else {
fs.unlink(filePath, () => {
});
console.log(`删除${file}文件成功`);
}
}
});
}
/**
* 删除指定路径下的所有空文件夹
*/
function rmEmptyDir(path, level = 0) {
const files = fs.readdirSync(path);
if (files.length > 0) {
let tempFile = 0;
files.forEach(file => {
tempFile++;
rmEmptyDir(`${path}/${file}`, 1);
});
if (tempFile === files.length && level !== 0) {
fs.rmdirSync(path);
}
} else {
level !== 0 && fs.rmdirSync(path);
}
}
/**
* 在复制目录前需要判断该目录是否存在,
* 不存在需要先创建目录
* @param src
* @param dst
* @param callback
*/
function exists(src, dst, callback) {
// 如果路径存在,则返回 true,否则返回 false。
if (fs.existsSync(dst)) {
callback(src, dst)
} else {
fs.mkdir(dst, function () {
callback(src, dst)
})
}
}
/**
* 判断数组中的元素是否包含此字符串
* @param arr
* @param obj
* @returns {boolean}
*/
function contains(arr, obj) {
let flag = false
arr.map((val) => {
if (obj.includes(val)) {
flag = true
}
})
return flag
}