1054 lines
30 KiB
JavaScript
1054 lines
30 KiB
JavaScript
import * as $filepath from "../filepath/filepath.mjs";
|
|
import * as $bit_array from "../gleam_stdlib/gleam/bit_array.mjs";
|
|
import * as $int from "../gleam_stdlib/gleam/int.mjs";
|
|
import * as $list from "../gleam_stdlib/gleam/list.mjs";
|
|
import * as $result from "../gleam_stdlib/gleam/result.mjs";
|
|
import * as $set from "../gleam_stdlib/gleam/set.mjs";
|
|
import * as $string from "../gleam_stdlib/gleam/string.mjs";
|
|
import {
|
|
Ok,
|
|
Error,
|
|
toList,
|
|
Empty as $Empty,
|
|
prepend as listPrepend,
|
|
CustomType as $CustomType,
|
|
makeError,
|
|
toBitArray,
|
|
} from "./gleam.mjs";
|
|
import {
|
|
fileInfo as file_info,
|
|
linkInfo as link_info,
|
|
readBits as read_bits,
|
|
writeBits as write_bits,
|
|
delete_ as delete$,
|
|
deleteFile as delete_file,
|
|
appendBits as append_bits,
|
|
isDirectory as is_directory,
|
|
createDirectory as create_directory,
|
|
createSymlink as create_symlink,
|
|
createLink as create_link,
|
|
readDirectory as read_directory,
|
|
isFile as is_file,
|
|
isSymlink as is_symlink,
|
|
createDirAll as do_create_dir_all,
|
|
copyFile as do_copy_file,
|
|
renameFile as rename_file,
|
|
renameFile as rename,
|
|
setPermissionsOctal as set_permissions_octal,
|
|
currentDirectory as current_directory,
|
|
} from "./simplifile_js.mjs";
|
|
|
|
export {
|
|
append_bits,
|
|
create_directory,
|
|
create_link,
|
|
create_symlink,
|
|
current_directory,
|
|
delete$,
|
|
delete_file,
|
|
file_info,
|
|
is_directory,
|
|
is_file,
|
|
is_symlink,
|
|
link_info,
|
|
read_bits,
|
|
read_directory,
|
|
rename,
|
|
rename_file,
|
|
set_permissions_octal,
|
|
write_bits,
|
|
};
|
|
|
|
const FILEPATH = "src/simplifile.gleam";
|
|
|
|
/**
|
|
* Permission denied.
|
|
*/
|
|
export class Eacces extends $CustomType {}
|
|
export const FileError$Eacces = () => new Eacces();
|
|
export const FileError$isEacces = (value) => value instanceof Eacces;
|
|
|
|
/**
|
|
* Resource temporarily unavailable.
|
|
*/
|
|
export class Eagain extends $CustomType {}
|
|
export const FileError$Eagain = () => new Eagain();
|
|
export const FileError$isEagain = (value) => value instanceof Eagain;
|
|
|
|
/**
|
|
* Bad file number
|
|
*/
|
|
export class Ebadf extends $CustomType {}
|
|
export const FileError$Ebadf = () => new Ebadf();
|
|
export const FileError$isEbadf = (value) => value instanceof Ebadf;
|
|
|
|
/**
|
|
* Bad message.
|
|
*/
|
|
export class Ebadmsg extends $CustomType {}
|
|
export const FileError$Ebadmsg = () => new Ebadmsg();
|
|
export const FileError$isEbadmsg = (value) => value instanceof Ebadmsg;
|
|
|
|
/**
|
|
* File busy.
|
|
*/
|
|
export class Ebusy extends $CustomType {}
|
|
export const FileError$Ebusy = () => new Ebusy();
|
|
export const FileError$isEbusy = (value) => value instanceof Ebusy;
|
|
|
|
/**
|
|
* Resource deadlock avoided.
|
|
*/
|
|
export class Edeadlk extends $CustomType {}
|
|
export const FileError$Edeadlk = () => new Edeadlk();
|
|
export const FileError$isEdeadlk = (value) => value instanceof Edeadlk;
|
|
|
|
/**
|
|
* On most architectures, same as `Edeadlk`. On some architectures, it
|
|
* means "File locking deadlock error."
|
|
*/
|
|
export class Edeadlock extends $CustomType {}
|
|
export const FileError$Edeadlock = () => new Edeadlock();
|
|
export const FileError$isEdeadlock = (value) => value instanceof Edeadlock;
|
|
|
|
/**
|
|
* Disk quota exceeded.
|
|
*/
|
|
export class Edquot extends $CustomType {}
|
|
export const FileError$Edquot = () => new Edquot();
|
|
export const FileError$isEdquot = (value) => value instanceof Edquot;
|
|
|
|
/**
|
|
* File already exists.
|
|
*/
|
|
export class Eexist extends $CustomType {}
|
|
export const FileError$Eexist = () => new Eexist();
|
|
export const FileError$isEexist = (value) => value instanceof Eexist;
|
|
|
|
/**
|
|
* Bad address in system call argument.
|
|
*/
|
|
export class Efault extends $CustomType {}
|
|
export const FileError$Efault = () => new Efault();
|
|
export const FileError$isEfault = (value) => value instanceof Efault;
|
|
|
|
/**
|
|
* File too large.
|
|
*/
|
|
export class Efbig extends $CustomType {}
|
|
export const FileError$Efbig = () => new Efbig();
|
|
export const FileError$isEfbig = (value) => value instanceof Efbig;
|
|
|
|
/**
|
|
* Inappropriate file type or format. Usually caused by trying to set the
|
|
* "sticky bit" on a regular file (not a directory).
|
|
*/
|
|
export class Eftype extends $CustomType {}
|
|
export const FileError$Eftype = () => new Eftype();
|
|
export const FileError$isEftype = (value) => value instanceof Eftype;
|
|
|
|
/**
|
|
* Interrupted system call.
|
|
*/
|
|
export class Eintr extends $CustomType {}
|
|
export const FileError$Eintr = () => new Eintr();
|
|
export const FileError$isEintr = (value) => value instanceof Eintr;
|
|
|
|
/**
|
|
* Invalid argument.
|
|
*/
|
|
export class Einval extends $CustomType {}
|
|
export const FileError$Einval = () => new Einval();
|
|
export const FileError$isEinval = (value) => value instanceof Einval;
|
|
|
|
/**
|
|
* I/O error.
|
|
*/
|
|
export class Eio extends $CustomType {}
|
|
export const FileError$Eio = () => new Eio();
|
|
export const FileError$isEio = (value) => value instanceof Eio;
|
|
|
|
/**
|
|
* Illegal operation on a directory.
|
|
*/
|
|
export class Eisdir extends $CustomType {}
|
|
export const FileError$Eisdir = () => new Eisdir();
|
|
export const FileError$isEisdir = (value) => value instanceof Eisdir;
|
|
|
|
/**
|
|
* Too many levels of symbolic links.
|
|
*/
|
|
export class Eloop extends $CustomType {}
|
|
export const FileError$Eloop = () => new Eloop();
|
|
export const FileError$isEloop = (value) => value instanceof Eloop;
|
|
|
|
/**
|
|
* Too many open files.
|
|
*/
|
|
export class Emfile extends $CustomType {}
|
|
export const FileError$Emfile = () => new Emfile();
|
|
export const FileError$isEmfile = (value) => value instanceof Emfile;
|
|
|
|
/**
|
|
* Too many links.
|
|
*/
|
|
export class Emlink extends $CustomType {}
|
|
export const FileError$Emlink = () => new Emlink();
|
|
export const FileError$isEmlink = (value) => value instanceof Emlink;
|
|
|
|
/**
|
|
* Multihop attempted.
|
|
*/
|
|
export class Emultihop extends $CustomType {}
|
|
export const FileError$Emultihop = () => new Emultihop();
|
|
export const FileError$isEmultihop = (value) => value instanceof Emultihop;
|
|
|
|
/**
|
|
* Filename too long
|
|
*/
|
|
export class Enametoolong extends $CustomType {}
|
|
export const FileError$Enametoolong = () => new Enametoolong();
|
|
export const FileError$isEnametoolong = (value) =>
|
|
value instanceof Enametoolong;
|
|
|
|
/**
|
|
* File table overflow
|
|
*/
|
|
export class Enfile extends $CustomType {}
|
|
export const FileError$Enfile = () => new Enfile();
|
|
export const FileError$isEnfile = (value) => value instanceof Enfile;
|
|
|
|
/**
|
|
* No buffer space available.
|
|
*/
|
|
export class Enobufs extends $CustomType {}
|
|
export const FileError$Enobufs = () => new Enobufs();
|
|
export const FileError$isEnobufs = (value) => value instanceof Enobufs;
|
|
|
|
/**
|
|
* No such device.
|
|
*/
|
|
export class Enodev extends $CustomType {}
|
|
export const FileError$Enodev = () => new Enodev();
|
|
export const FileError$isEnodev = (value) => value instanceof Enodev;
|
|
|
|
/**
|
|
* No locks available.
|
|
*/
|
|
export class Enolck extends $CustomType {}
|
|
export const FileError$Enolck = () => new Enolck();
|
|
export const FileError$isEnolck = (value) => value instanceof Enolck;
|
|
|
|
/**
|
|
* Link has been severed.
|
|
*/
|
|
export class Enolink extends $CustomType {}
|
|
export const FileError$Enolink = () => new Enolink();
|
|
export const FileError$isEnolink = (value) => value instanceof Enolink;
|
|
|
|
/**
|
|
* No such file or directory.
|
|
*/
|
|
export class Enoent extends $CustomType {}
|
|
export const FileError$Enoent = () => new Enoent();
|
|
export const FileError$isEnoent = (value) => value instanceof Enoent;
|
|
|
|
/**
|
|
* Not enough memory.
|
|
*/
|
|
export class Enomem extends $CustomType {}
|
|
export const FileError$Enomem = () => new Enomem();
|
|
export const FileError$isEnomem = (value) => value instanceof Enomem;
|
|
|
|
/**
|
|
* No space left on device.
|
|
*/
|
|
export class Enospc extends $CustomType {}
|
|
export const FileError$Enospc = () => new Enospc();
|
|
export const FileError$isEnospc = (value) => value instanceof Enospc;
|
|
|
|
/**
|
|
* No STREAM resources.
|
|
*/
|
|
export class Enosr extends $CustomType {}
|
|
export const FileError$Enosr = () => new Enosr();
|
|
export const FileError$isEnosr = (value) => value instanceof Enosr;
|
|
|
|
/**
|
|
* Not a STREAM.
|
|
*/
|
|
export class Enostr extends $CustomType {}
|
|
export const FileError$Enostr = () => new Enostr();
|
|
export const FileError$isEnostr = (value) => value instanceof Enostr;
|
|
|
|
/**
|
|
* Function not implemented.
|
|
*/
|
|
export class Enosys extends $CustomType {}
|
|
export const FileError$Enosys = () => new Enosys();
|
|
export const FileError$isEnosys = (value) => value instanceof Enosys;
|
|
|
|
/**
|
|
* Block device required.
|
|
*/
|
|
export class Enotblk extends $CustomType {}
|
|
export const FileError$Enotblk = () => new Enotblk();
|
|
export const FileError$isEnotblk = (value) => value instanceof Enotblk;
|
|
|
|
/**
|
|
* Not a directory.
|
|
*/
|
|
export class Enotdir extends $CustomType {}
|
|
export const FileError$Enotdir = () => new Enotdir();
|
|
export const FileError$isEnotdir = (value) => value instanceof Enotdir;
|
|
|
|
/**
|
|
* Operation not supported.
|
|
*/
|
|
export class Enotsup extends $CustomType {}
|
|
export const FileError$Enotsup = () => new Enotsup();
|
|
export const FileError$isEnotsup = (value) => value instanceof Enotsup;
|
|
|
|
/**
|
|
* No such device or address.
|
|
*/
|
|
export class Enxio extends $CustomType {}
|
|
export const FileError$Enxio = () => new Enxio();
|
|
export const FileError$isEnxio = (value) => value instanceof Enxio;
|
|
|
|
/**
|
|
* Operation not supported on socket.
|
|
*/
|
|
export class Eopnotsupp extends $CustomType {}
|
|
export const FileError$Eopnotsupp = () => new Eopnotsupp();
|
|
export const FileError$isEopnotsupp = (value) => value instanceof Eopnotsupp;
|
|
|
|
/**
|
|
* Value too large to be stored in data type.
|
|
*/
|
|
export class Eoverflow extends $CustomType {}
|
|
export const FileError$Eoverflow = () => new Eoverflow();
|
|
export const FileError$isEoverflow = (value) => value instanceof Eoverflow;
|
|
|
|
/**
|
|
* Not owner.
|
|
*/
|
|
export class Eperm extends $CustomType {}
|
|
export const FileError$Eperm = () => new Eperm();
|
|
export const FileError$isEperm = (value) => value instanceof Eperm;
|
|
|
|
/**
|
|
* Broken pipe.
|
|
*/
|
|
export class Epipe extends $CustomType {}
|
|
export const FileError$Epipe = () => new Epipe();
|
|
export const FileError$isEpipe = (value) => value instanceof Epipe;
|
|
|
|
/**
|
|
* Result too large.
|
|
*/
|
|
export class Erange extends $CustomType {}
|
|
export const FileError$Erange = () => new Erange();
|
|
export const FileError$isErange = (value) => value instanceof Erange;
|
|
|
|
/**
|
|
* Read-only file system.
|
|
*/
|
|
export class Erofs extends $CustomType {}
|
|
export const FileError$Erofs = () => new Erofs();
|
|
export const FileError$isErofs = (value) => value instanceof Erofs;
|
|
|
|
/**
|
|
* Invalid seek.
|
|
*/
|
|
export class Espipe extends $CustomType {}
|
|
export const FileError$Espipe = () => new Espipe();
|
|
export const FileError$isEspipe = (value) => value instanceof Espipe;
|
|
|
|
/**
|
|
* No such process.
|
|
*/
|
|
export class Esrch extends $CustomType {}
|
|
export const FileError$Esrch = () => new Esrch();
|
|
export const FileError$isEsrch = (value) => value instanceof Esrch;
|
|
|
|
/**
|
|
* Stale remote file handle.
|
|
*/
|
|
export class Estale extends $CustomType {}
|
|
export const FileError$Estale = () => new Estale();
|
|
export const FileError$isEstale = (value) => value instanceof Estale;
|
|
|
|
/**
|
|
* Text file busy.
|
|
*/
|
|
export class Etxtbsy extends $CustomType {}
|
|
export const FileError$Etxtbsy = () => new Etxtbsy();
|
|
export const FileError$isEtxtbsy = (value) => value instanceof Etxtbsy;
|
|
|
|
/**
|
|
* Cross-domain link.
|
|
*/
|
|
export class Exdev extends $CustomType {}
|
|
export const FileError$Exdev = () => new Exdev();
|
|
export const FileError$isExdev = (value) => value instanceof Exdev;
|
|
|
|
/**
|
|
* File was requested to be read as UTF-8, but is not UTF-8 encoded.
|
|
*/
|
|
export class NotUtf8 extends $CustomType {}
|
|
export const FileError$NotUtf8 = () => new NotUtf8();
|
|
export const FileError$isNotUtf8 = (value) => value instanceof NotUtf8;
|
|
|
|
/**
|
|
* Any error not accounted for by this type
|
|
*/
|
|
export class Unknown extends $CustomType {
|
|
constructor(inner) {
|
|
super();
|
|
this.inner = inner;
|
|
}
|
|
}
|
|
export const FileError$Unknown = (inner) => new Unknown(inner);
|
|
export const FileError$isUnknown = (value) => value instanceof Unknown;
|
|
export const FileError$Unknown$inner = (value) => value.inner;
|
|
export const FileError$Unknown$0 = (value) => value.inner;
|
|
|
|
export class FileInfo extends $CustomType {
|
|
constructor(size, mode, nlinks, inode, user_id, group_id, dev, atime_seconds, mtime_seconds, ctime_seconds) {
|
|
super();
|
|
this.size = size;
|
|
this.mode = mode;
|
|
this.nlinks = nlinks;
|
|
this.inode = inode;
|
|
this.user_id = user_id;
|
|
this.group_id = group_id;
|
|
this.dev = dev;
|
|
this.atime_seconds = atime_seconds;
|
|
this.mtime_seconds = mtime_seconds;
|
|
this.ctime_seconds = ctime_seconds;
|
|
}
|
|
}
|
|
export const FileInfo$FileInfo = (size, mode, nlinks, inode, user_id, group_id, dev, atime_seconds, mtime_seconds, ctime_seconds) =>
|
|
new FileInfo(size,
|
|
mode,
|
|
nlinks,
|
|
inode,
|
|
user_id,
|
|
group_id,
|
|
dev,
|
|
atime_seconds,
|
|
mtime_seconds,
|
|
ctime_seconds);
|
|
export const FileInfo$isFileInfo = (value) => value instanceof FileInfo;
|
|
export const FileInfo$FileInfo$size = (value) => value.size;
|
|
export const FileInfo$FileInfo$0 = (value) => value.size;
|
|
export const FileInfo$FileInfo$mode = (value) => value.mode;
|
|
export const FileInfo$FileInfo$1 = (value) => value.mode;
|
|
export const FileInfo$FileInfo$nlinks = (value) => value.nlinks;
|
|
export const FileInfo$FileInfo$2 = (value) => value.nlinks;
|
|
export const FileInfo$FileInfo$inode = (value) => value.inode;
|
|
export const FileInfo$FileInfo$3 = (value) => value.inode;
|
|
export const FileInfo$FileInfo$user_id = (value) => value.user_id;
|
|
export const FileInfo$FileInfo$4 = (value) => value.user_id;
|
|
export const FileInfo$FileInfo$group_id = (value) => value.group_id;
|
|
export const FileInfo$FileInfo$5 = (value) => value.group_id;
|
|
export const FileInfo$FileInfo$dev = (value) => value.dev;
|
|
export const FileInfo$FileInfo$6 = (value) => value.dev;
|
|
export const FileInfo$FileInfo$atime_seconds = (value) => value.atime_seconds;
|
|
export const FileInfo$FileInfo$7 = (value) => value.atime_seconds;
|
|
export const FileInfo$FileInfo$mtime_seconds = (value) => value.mtime_seconds;
|
|
export const FileInfo$FileInfo$8 = (value) => value.mtime_seconds;
|
|
export const FileInfo$FileInfo$ctime_seconds = (value) => value.ctime_seconds;
|
|
export const FileInfo$FileInfo$9 = (value) => value.ctime_seconds;
|
|
|
|
/**
|
|
* A regular file
|
|
*/
|
|
export class File extends $CustomType {}
|
|
export const FileType$File = () => new File();
|
|
export const FileType$isFile = (value) => value instanceof File;
|
|
|
|
/**
|
|
* A directory
|
|
*/
|
|
export class Directory extends $CustomType {}
|
|
export const FileType$Directory = () => new Directory();
|
|
export const FileType$isDirectory = (value) => value instanceof Directory;
|
|
|
|
/**
|
|
* A symbolic link
|
|
*/
|
|
export class Symlink extends $CustomType {}
|
|
export const FileType$Symlink = () => new Symlink();
|
|
export const FileType$isSymlink = (value) => value instanceof Symlink;
|
|
|
|
/**
|
|
* Another special file type present on some systems, lika a socket or device
|
|
*/
|
|
export class Other extends $CustomType {}
|
|
export const FileType$Other = () => new Other();
|
|
export const FileType$isOther = (value) => value instanceof Other;
|
|
|
|
export class Read extends $CustomType {}
|
|
export const Permission$Read = () => new Read();
|
|
export const Permission$isRead = (value) => value instanceof Read;
|
|
|
|
export class Write extends $CustomType {}
|
|
export const Permission$Write = () => new Write();
|
|
export const Permission$isWrite = (value) => value instanceof Write;
|
|
|
|
export class Execute extends $CustomType {}
|
|
export const Permission$Execute = () => new Execute();
|
|
export const Permission$isExecute = (value) => value instanceof Execute;
|
|
|
|
export class FilePermissions extends $CustomType {
|
|
constructor(user, group, other) {
|
|
super();
|
|
this.user = user;
|
|
this.group = group;
|
|
this.other = other;
|
|
}
|
|
}
|
|
export const FilePermissions$FilePermissions = (user, group, other) =>
|
|
new FilePermissions(user, group, other);
|
|
export const FilePermissions$isFilePermissions = (value) =>
|
|
value instanceof FilePermissions;
|
|
export const FilePermissions$FilePermissions$user = (value) => value.user;
|
|
export const FilePermissions$FilePermissions$0 = (value) => value.user;
|
|
export const FilePermissions$FilePermissions$group = (value) => value.group;
|
|
export const FilePermissions$FilePermissions$1 = (value) => value.group;
|
|
export const FilePermissions$FilePermissions$other = (value) => value.other;
|
|
export const FilePermissions$FilePermissions$2 = (value) => value.other;
|
|
|
|
/**
|
|
* Convert an error into a human-readable description
|
|
* ## Example
|
|
* ```gleam
|
|
* let assert "Input/output error" = describe_error(Eio)
|
|
* ```
|
|
*/
|
|
export function describe_error(error) {
|
|
if (error instanceof Eacces) {
|
|
return "Permission denied";
|
|
} else if (error instanceof Eagain) {
|
|
return "Resource temporarily unavailable";
|
|
} else if (error instanceof Ebadf) {
|
|
return "Bad file descriptor";
|
|
} else if (error instanceof Ebadmsg) {
|
|
return "Bad message";
|
|
} else if (error instanceof Ebusy) {
|
|
return "Resource busy";
|
|
} else if (error instanceof Edeadlk) {
|
|
return "Resource deadlock avoided";
|
|
} else if (error instanceof Edeadlock) {
|
|
return "Resource deadlock avoided";
|
|
} else if (error instanceof Edquot) {
|
|
return "Disc quota exceeded";
|
|
} else if (error instanceof Eexist) {
|
|
return "File exists";
|
|
} else if (error instanceof Efault) {
|
|
return "Bad address";
|
|
} else if (error instanceof Efbig) {
|
|
return "File too large";
|
|
} else if (error instanceof Eftype) {
|
|
return "Inappropriate file type or format";
|
|
} else if (error instanceof Eintr) {
|
|
return "Interrupted system call";
|
|
} else if (error instanceof Einval) {
|
|
return "Invalid argument";
|
|
} else if (error instanceof Eio) {
|
|
return "Input/output error";
|
|
} else if (error instanceof Eisdir) {
|
|
return "Is a directory";
|
|
} else if (error instanceof Eloop) {
|
|
return "Too many levels of symbolic links";
|
|
} else if (error instanceof Emfile) {
|
|
return "Too many open files";
|
|
} else if (error instanceof Emlink) {
|
|
return "Too many links";
|
|
} else if (error instanceof Emultihop) {
|
|
return "Multihop attempted";
|
|
} else if (error instanceof Enametoolong) {
|
|
return "File name too long";
|
|
} else if (error instanceof Enfile) {
|
|
return "Too many open files in system";
|
|
} else if (error instanceof Enobufs) {
|
|
return "No buffer space available";
|
|
} else if (error instanceof Enodev) {
|
|
return "Operation not supported by device";
|
|
} else if (error instanceof Enolck) {
|
|
return "No locks available";
|
|
} else if (error instanceof Enolink) {
|
|
return "Link has been severed";
|
|
} else if (error instanceof Enoent) {
|
|
return "No such file or directory";
|
|
} else if (error instanceof Enomem) {
|
|
return "Cannot allocate memory";
|
|
} else if (error instanceof Enospc) {
|
|
return "No space left on device";
|
|
} else if (error instanceof Enosr) {
|
|
return "No STREAM resources";
|
|
} else if (error instanceof Enostr) {
|
|
return "Not a STREAM";
|
|
} else if (error instanceof Enosys) {
|
|
return "Function not implemented";
|
|
} else if (error instanceof Enotblk) {
|
|
return "Block device required";
|
|
} else if (error instanceof Enotdir) {
|
|
return "Not a directory";
|
|
} else if (error instanceof Enotsup) {
|
|
return "Operation not supported";
|
|
} else if (error instanceof Enxio) {
|
|
return "Device not configured";
|
|
} else if (error instanceof Eopnotsupp) {
|
|
return "Operation not supported on socket";
|
|
} else if (error instanceof Eoverflow) {
|
|
return "Value too large to be stored in data type";
|
|
} else if (error instanceof Eperm) {
|
|
return "Operation not permitted";
|
|
} else if (error instanceof Epipe) {
|
|
return "Broken pipe";
|
|
} else if (error instanceof Erange) {
|
|
return "Result too large";
|
|
} else if (error instanceof Erofs) {
|
|
return "Read-only file system";
|
|
} else if (error instanceof Espipe) {
|
|
return "Illegal seek";
|
|
} else if (error instanceof Esrch) {
|
|
return "No such process";
|
|
} else if (error instanceof Estale) {
|
|
return "Stale NFS file handle";
|
|
} else if (error instanceof Etxtbsy) {
|
|
return "Text file busy";
|
|
} else if (error instanceof Exdev) {
|
|
return "Cross-device link";
|
|
} else if (error instanceof NotUtf8) {
|
|
return "File not UTF-8 encoded";
|
|
} else {
|
|
let inner = error.inner;
|
|
return "Unknown error: " + inner;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extract the file permissions from a given FileInfo value in their octal representation.
|
|
*
|
|
* ## Example
|
|
* ```gleam
|
|
* use info <- result.try(simplifile.file_info("src/app.gleam"))
|
|
* simplifile.file_info_permissions_octal(info)
|
|
* // --> 0o644
|
|
* ```
|
|
*/
|
|
export function file_info_permissions_octal(file_info) {
|
|
return $int.bitwise_and(file_info.mode, 0o777);
|
|
}
|
|
|
|
function integer_to_permissions(integer) {
|
|
let $ = $int.bitwise_and(integer, 7);
|
|
if ($ === 7) {
|
|
return $set.from_list(toList([new Read(), new Write(), new Execute()]));
|
|
} else if ($ === 6) {
|
|
return $set.from_list(toList([new Read(), new Write()]));
|
|
} else if ($ === 5) {
|
|
return $set.from_list(toList([new Read(), new Execute()]));
|
|
} else if ($ === 3) {
|
|
return $set.from_list(toList([new Write(), new Execute()]));
|
|
} else if ($ === 4) {
|
|
return $set.from_list(toList([new Read()]));
|
|
} else if ($ === 2) {
|
|
return $set.from_list(toList([new Write()]));
|
|
} else if ($ === 1) {
|
|
return $set.from_list(toList([new Execute()]));
|
|
} else if ($ === 0) {
|
|
return $set.new$();
|
|
} else {
|
|
throw makeError(
|
|
"panic",
|
|
FILEPATH,
|
|
"simplifile",
|
|
674,
|
|
"integer_to_permissions",
|
|
"`panic` expression evaluated.",
|
|
{}
|
|
)
|
|
}
|
|
}
|
|
|
|
function octal_to_file_permissions(octal) {
|
|
return new FilePermissions(
|
|
(() => {
|
|
let _pipe = octal;
|
|
let _pipe$1 = $int.bitwise_shift_right(_pipe, 6);
|
|
return integer_to_permissions(_pipe$1);
|
|
})(),
|
|
(() => {
|
|
let _pipe = octal;
|
|
let _pipe$1 = $int.bitwise_shift_right(_pipe, 3);
|
|
return integer_to_permissions(_pipe$1);
|
|
})(),
|
|
(() => {
|
|
let _pipe = octal;
|
|
return integer_to_permissions(_pipe);
|
|
})(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Extract the `FilePermissions` from a given FileInfo value.
|
|
*/
|
|
export function file_info_permissions(file_info) {
|
|
return octal_to_file_permissions(file_info_permissions_octal(file_info));
|
|
}
|
|
|
|
/**
|
|
* Extract the file type from a given FileInfo value.
|
|
*
|
|
* ## Example
|
|
* ```gleam
|
|
* use info <- result.try(simplifile.file_info("src/app.gleam"))
|
|
* simplifile.file_info_type(info)
|
|
* // --> simplifile.File
|
|
* ```
|
|
*/
|
|
export function file_info_type(file_info) {
|
|
let $ = $int.bitwise_and(file_info.mode, 0o170000);
|
|
if ($ === 32768) {
|
|
return new File();
|
|
} else if ($ === 16384) {
|
|
return new Directory();
|
|
} else if ($ === 40960) {
|
|
return new Symlink();
|
|
} else {
|
|
return new Other();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read a files contents as a string
|
|
* ## Example
|
|
* ```gleam
|
|
* let assert Ok(records) = read(from: "./users.csv")
|
|
* ```
|
|
*/
|
|
export function read(filepath) {
|
|
let $ = read_bits(filepath);
|
|
if ($ instanceof Ok) {
|
|
let bits = $[0];
|
|
let $1 = $bit_array.to_string(bits);
|
|
if ($1 instanceof Ok) {
|
|
return $1;
|
|
} else {
|
|
return new Error(new NotUtf8());
|
|
}
|
|
} else {
|
|
return $;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Write a string to a file at the given path
|
|
* ## Example
|
|
* ```gleam
|
|
* let assert Ok(Nil) = write(to: "./hello_world.txt", contents: "Hello, World!")
|
|
* ```
|
|
*/
|
|
export function write(filepath, contents) {
|
|
let _pipe = contents;
|
|
let _pipe$1 = $bit_array.from_string(_pipe);
|
|
return write_bits(filepath, _pipe$1);
|
|
}
|
|
|
|
/**
|
|
* Delete all files/directories specified in a list of paths.
|
|
* Recursively deletes provided directories.
|
|
* Does not return an error if one or more of the provided paths
|
|
* do not exist.
|
|
*/
|
|
export function delete_all(loop$paths) {
|
|
while (true) {
|
|
let paths = loop$paths;
|
|
if (paths instanceof $Empty) {
|
|
return new Ok(undefined);
|
|
} else {
|
|
let path = paths.head;
|
|
let rest = paths.tail;
|
|
let $ = delete$(path);
|
|
if ($ instanceof Ok) {
|
|
loop$paths = rest;
|
|
} else {
|
|
let $1 = $[0];
|
|
if ($1 instanceof Enoent) {
|
|
loop$paths = rest;
|
|
} else {
|
|
return $;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Append a string to the contents of a file at the given path
|
|
* ## Example
|
|
* ```gleam
|
|
* let assert Ok(Nil) = append(to: "./needs_more_text.txt", contents: "more text")
|
|
* ```
|
|
*/
|
|
export function append(filepath, contents) {
|
|
let _pipe = contents;
|
|
let _pipe$1 = $bit_array.from_string(_pipe);
|
|
return append_bits(filepath, _pipe$1);
|
|
}
|
|
|
|
/**
|
|
* Creates an empty file at the given filepath. Returns an `Error(Eexist)`
|
|
* if the file already exists.
|
|
*/
|
|
export function create_file(filepath) {
|
|
let $ = (() => {
|
|
let _pipe = filepath;
|
|
return is_file(_pipe);
|
|
})();
|
|
let $1 = (() => {
|
|
let _pipe = filepath;
|
|
return is_directory(_pipe);
|
|
})();
|
|
if ($ instanceof Ok) {
|
|
let $2 = $[0];
|
|
if ($2) {
|
|
return new Error(new Eexist());
|
|
} else if ($1 instanceof Ok) {
|
|
let $3 = $1[0];
|
|
if ($3) {
|
|
return new Error(new Eexist());
|
|
} else {
|
|
return write_bits(filepath, toBitArray([]));
|
|
}
|
|
} else {
|
|
return write_bits(filepath, toBitArray([]));
|
|
}
|
|
} else if ($1 instanceof Ok) {
|
|
let $2 = $1[0];
|
|
if ($2) {
|
|
return new Error(new Eexist());
|
|
} else {
|
|
return write_bits(filepath, toBitArray([]));
|
|
}
|
|
} else {
|
|
return write_bits(filepath, toBitArray([]));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recursively creates necessary directories for a given directory
|
|
* path. Note that if you pass a path that "looks like" a file, i.e.
|
|
* `./a/b.txt`, a folder named `b.txt` will be created, so be sure
|
|
* to pass only the path to the required directory.
|
|
*/
|
|
export function create_directory_all(dirpath) {
|
|
return do_create_dir_all(dirpath + "/");
|
|
}
|
|
|
|
function do_copy_directory(src, dest) {
|
|
return $result.try$(
|
|
read_directory(src),
|
|
(segments) => {
|
|
let _pipe = segments;
|
|
$list.each(
|
|
_pipe,
|
|
(segment) => {
|
|
let src_path = $filepath.join(src, segment);
|
|
let dest_path = $filepath.join(dest, segment);
|
|
return $result.try$(
|
|
file_info(src_path),
|
|
(src_info) => {
|
|
let $ = file_info_type(src_info);
|
|
if ($ instanceof File) {
|
|
return $result.try$(
|
|
read_bits(src_path),
|
|
(content) => {
|
|
let _pipe$1 = content;
|
|
return write_bits(dest_path, _pipe$1);
|
|
},
|
|
);
|
|
} else if ($ instanceof Directory) {
|
|
return $result.try$(
|
|
create_directory(dest_path),
|
|
(_) => { return do_copy_directory(src_path, dest_path); },
|
|
);
|
|
} else if ($ instanceof Symlink) {
|
|
return new Error(
|
|
new Unknown(
|
|
"This is an internal bug where the `file_info` is somehow returning info about a simlink. Please file an issue on the simplifile repo.",
|
|
),
|
|
);
|
|
} else {
|
|
return new Error(
|
|
new Unknown(
|
|
"Unknown file type (not file, directory, or simlink)",
|
|
),
|
|
);
|
|
}
|
|
},
|
|
);
|
|
},
|
|
);
|
|
return new Ok(undefined);
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Copy a directory recursively
|
|
*/
|
|
export function copy_directory(src, dest) {
|
|
return $result.try$(
|
|
create_directory_all(dest),
|
|
(_) => { return do_copy_directory(src, dest); },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Copy a file at a given path to another path.
|
|
* Note: destination should include the filename, not just the directory
|
|
*/
|
|
export function copy_file(src, dest) {
|
|
let _pipe = do_copy_file(src, dest);
|
|
return $result.replace(_pipe, undefined);
|
|
}
|
|
|
|
/**
|
|
* Copy a file or a directory to a new path. Copies directories recursively.
|
|
*
|
|
* ### Performance Note
|
|
* This function does work to determine if the src path
|
|
* points to a file or a directory. Consider using one of the the dedicated
|
|
* functions `copy_file` or `copy_directory` if you already know which one you need.
|
|
*/
|
|
export function copy(src, dest) {
|
|
return $result.try$(
|
|
file_info(src),
|
|
(src_info) => {
|
|
let $ = file_info_type(src_info);
|
|
if ($ instanceof File) {
|
|
return copy_file(src, dest);
|
|
} else if ($ instanceof Directory) {
|
|
return copy_directory(src, dest);
|
|
} else if ($ instanceof Symlink) {
|
|
return new Error(
|
|
new Unknown(
|
|
"This is an internal bug where the `file_info` is somehow returning info about a simlink. Please file an issue on the simplifile repo.",
|
|
),
|
|
);
|
|
} else {
|
|
return new Error(
|
|
new Unknown("Unknown file type (not file, directory, or simlink)"),
|
|
);
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Copy a directory recursively and then delete the old one.
|
|
*/
|
|
export function rename_directory(src, dest) {
|
|
return $result.try$(
|
|
copy_directory(src, dest),
|
|
(_) => { return delete$(src); },
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Clear the contents of a directory, deleting all files and directories within
|
|
* but leaving the top level directory in place.
|
|
*/
|
|
export function clear_directory(path) {
|
|
return $result.try$(
|
|
read_directory(path),
|
|
(paths) => {
|
|
let _pipe = paths;
|
|
let _pipe$1 = $list.map(
|
|
_pipe,
|
|
(_capture) => { return $filepath.join(path, _capture); },
|
|
);
|
|
return delete_all(_pipe$1);
|
|
},
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a list of filepaths for every file in the directory, including nested
|
|
* files.
|
|
*/
|
|
export function get_files(directory) {
|
|
return $result.try$(
|
|
read_directory(directory),
|
|
(contents) => {
|
|
return $list.try_fold(
|
|
contents,
|
|
toList([]),
|
|
(acc, content) => {
|
|
let path = $filepath.join(directory, content);
|
|
return $result.try$(
|
|
file_info(path),
|
|
(info) => {
|
|
let $ = file_info_type(info);
|
|
if ($ instanceof File) {
|
|
return new Ok(listPrepend(path, acc));
|
|
} else if ($ instanceof Directory) {
|
|
return $result.try$(
|
|
get_files(path),
|
|
(nested_files) => {
|
|
return new Ok($list.append(acc, nested_files));
|
|
},
|
|
);
|
|
} else {
|
|
return new Ok(acc);
|
|
}
|
|
},
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
function permission_to_integer(permission) {
|
|
if (permission instanceof Read) {
|
|
return 0o4;
|
|
} else if (permission instanceof Write) {
|
|
return 0o2;
|
|
} else {
|
|
return 0o1;
|
|
}
|
|
}
|
|
|
|
export function file_permissions_to_octal(permissions) {
|
|
let make_permission_digit = (permissions) => {
|
|
let _pipe = permissions;
|
|
let _pipe$1 = $set.to_list(_pipe);
|
|
let _pipe$2 = $list.map(_pipe$1, permission_to_integer);
|
|
return $int.sum(_pipe$2);
|
|
};
|
|
return (make_permission_digit(permissions.user) * 64 + make_permission_digit(
|
|
permissions.group,
|
|
) * 8) + make_permission_digit(permissions.other);
|
|
}
|
|
|
|
/**
|
|
* Sets the permissions for a given file
|
|
*
|
|
* # Example
|
|
* ```gleam
|
|
* let all = set.from_list([Read, Write, Execute])
|
|
* let all = FilePermissions(user: all, group: all, other: all)
|
|
* let assert Ok(Nil) = set_permissions("./script.sh", all)
|
|
* ```
|
|
*/
|
|
export function set_permissions(filepath, permissions) {
|
|
return set_permissions_octal(filepath, file_permissions_to_octal(permissions));
|
|
}
|