Skip to content

Instantly share code, notes, and snippets.

@bendman
Created December 10, 2015 03:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bendman/23f7b7e9905106c4ed48 to your computer and use it in GitHub Desktop.
Save bendman/23f7b7e9905106c4ed48 to your computer and use it in GitHub Desktop.
Fix broken symlink binaries to be relative symlinks
// Find symlinks that don't work and fix them.
//
// This is done by:
// 1. Getting a list of all file paths in a directory
// 2. Filtering for broken symlinks by reading binary content as unicode
// 5. Determining relative path between source and target
// 6. Deleting old link file
// 7. Creating new relative link file
var fs = require('fs');
var path = require('path');
var SYMLINK_ROOT = '!<symlink>/home/Piotr/SVN/freedict/trunk/';
var BROKEN_SYMLINK_PREFIX = /!<symlink>��/;
var SKIPPED_FILES = /(\.git|symlinkFixer)/;
var ROOT = path.resolve(__dirname, '.');
var IGNORE_UNICODES = [
0, // null
65533 // replacement
];
// Start
recurseDirExecute(ROOT, function(err, filePath) {
fs.readFile(filePath, 'utf8', function(err, data) {
err && console.log(err);
// Filter for broken symlinks
if (data.match(BROKEN_SYMLINK_PREFIX)) {
var content = getCleanString(data);
var targetAbsPath = path.resolve(ROOT, content.replace(SYMLINK_ROOT, './'));
handleSymlink(path.resolve(ROOT, filePath), targetAbsPath);
}
});
});
function handleSymlink(filePath, targetPath) {
var relativePath = path.relative(path.resolve(filePath, '..'), targetPath);
if (!relativePath.match('../')) return;
// console.log('file', relativePath);
fs.unlink(filePath, function(err) {
if (err) console.error('unlink error:', err);
fs.symlink(relativePath, filePath, function(err) {
if (err) console.error('symlink error:', err);
});
});
}
//
// Utilities
//
function recurseDirExecute(dirPath, done) {
dirExecute(dirPath, function(err, innerPath) {
if (err) {
console.error('dirExecute Error:', err);
return;
}
fs.stat(innerPath, function(err, stats) {
// handle errors
if (err) {
console.error('Stat Error:', err);
return;
}
if (innerPath.match(SKIPPED_FILES)) {
// skip certain files
return;
} else if (stats && stats.isDirectory()) {
// recurse directories
recurseDirExecute(path.join(innerPath), done);
} else {
// execute remaining
done(err, innerPath);
}
});
});
}
function dirExecute(dirpath, done) {
fs.readdir(dirpath, function(err, files) {
files.forEach(function(file) {
done(err, path.join(dirpath, file));
});
});
}
function getCleanString(string) {
var charCodes = Array.prototype.map.call(string, function(char) {
return char.charCodeAt();
}).filter(function(charCode) {
return (IGNORE_UNICODES.indexOf(charCode) === -1);
});
return String.fromCharCode.apply(String, charCodes);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment