/*
* Copyright (c) 2020 Capgemini Group, Commissariat à l'énergie atomique et aux énergies alternatives,
* OW2, Sysgo AG, Technikon, Tree Technology, Universitat Politècnica de València.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
/** A File
*/
class File
{
/** constructor
*
* @param {string} rel_path - path relative to root directory
* @param {(string|Buffer)} [content] - content of file
* @param {string} [encoding] - text encoding of a text file (implicitely null for raw buffer, undefined if same as global file system text encoding)
* @param {string} [type] - type
* @param {string} [mime_type] - MIME type
* @param {string} [git_working_tree] - URL of git repository
* @param {boolean} [git_dirty] - Git dirty flag
* @param {boolean} [git_unmerged] - Git unmerged flag
*/
constructor(rel_path, content = undefined, encoding = 'utf8', type = '', mime_type = '', git_working_tree = undefined, git_dirty = undefined, git_unmerged = undefined)
{
const path = require('path');
this.rel_path = path.posix.normalize(rel_path);
if(this.rel_path.startsWith('/')) this.rel_path = this.rel_path.slice(1); // make sure path is really relative (no leading '/')
this.content = content;
this.encoding = Buffer.isBuffer(content) ? null : encoding;
this.type = type;
this.mime_type = mime_type;
if(git_working_tree !== undefined) this.git_working_tree = git_working_tree;
if(git_dirty !== undefined) this.git_dirty = git_dirty;
if(git_unmerged !== undefined) this.git_unmerged = git_unmerged;
}
/** Compare content with another file
*
* @param {File} other - other file to compare content with
* @return {number} sort order (0 means equal)
*/
compare_content(other)
{
const a = Buffer.isBuffer(this.content) ? this.content : Buffer.from(this.content, this.encoding);
const b = Buffer.isBuffer(other.content) ? other.content : Buffer.from(other.content, other.encoding);
return a.compare(b);
}
/** Get the absolute path of the file (on the host file system)
*
* @param {string} root_directory_path - the root directory path on the host file system
* @return {string} the absolute path of the file
*/
get_abs_path(root_directory_path)
{
const path = require('path');
return path.normalize(path.join(root_directory_path, this.rel_path));
}
/** Build a File instance from an object, convenient for transportation with a transport protocol, that looks like a file but with an additional property 'format'.
* If a property 'format' exists in the object then property 'content' is considered
* as a base64 encoded string that is converted to a buffer in the File instance.
*
* @param {Object} obj - an object
* @return {File} an instance of File
*/
static from(obj)
{
return new File(
obj.rel_path, // rel_path
(obj.format == 'binary') ? (obj.content ? Buffer.from(obj.content, 'base64') : Buffer.alloc(0)) : obj.content, // content
obj.encoding, // encoding
obj.type, // type
obj.mime_type, // MIME type
obj.git_working_tree, // Git working tree
obj.git_dirty, // Git dirty
obj.git_unmerged // Git unmerged
);
}
/** Export the file as an object convenient for transportation with a transport protocol.
* It has property 'format' which value is 'binary' when the property 'content' of the object is a base64 encoded string, otherwise its value is 'text'.
*
* @return {Object} an object
*/
export()
{
let obj =
{
rel_path : this.rel_path
};
if(this.content !== undefined)
{
obj.content = Buffer.isBuffer(this.content) ? this.content.toString('base64') : this.content;
obj.format = Buffer.isBuffer(this.content) ? 'binary' : 'text';
}
if((this.encoding !== undefined) && (this.encoding !== null))
{
obj.encoding = this.encoding;
}
if(this.type !== undefined)
{
obj.type = this.type;
}
if(this.mime_type !== undefined)
{
obj.mime_type = this.mime_type;
}
if(this.git_working_tree !== undefined)
{
obj.git_working_tree = this.git_working_tree;
}
if(this.git_dirty !== undefined)
{
obj.git_dirty = this.git_dirty;
}
if(this.git_unmerged !== undefined)
{
obj.git_unmerged = this.git_unmerged;
}
return obj;
}
/** Build a File instance from an object from the database.
*
* @param {Object} obj - an object from database
* @return {File} an instance of File
*/
static from_database(obj)
{
return new File(
obj.filename, // rel_path
(obj.fileFormat == 'binary') ? (obj.filecontent ? Buffer.from(obj.filecontent, 'base64') : Buffer.alloc(0)) : obj.filecontent, // content
obj.fileEncoding, // encoding
obj.fileType, // type
obj.fileMimeType, // MIME type
obj.gitWorkingTree,// Git working tree
obj.gitDirty, // Git dirty
obj.gitUnmerged // Git unmerged
);
}
/** Export the file as an object convenient for storing in the database.
* It has property 'format' which value is 'binary' when the property 'content' of the object is a base64 encoded string, otherwise its value is 'text'.
*
* @return {Object} an object
*/
database_export()
{
let obj =
{
filename : this.rel_path
};
if(this.content !== undefined)
{
obj.filecontent = Buffer.isBuffer(this.content) ? this.content.toString('base64') : this.content;
}
if(this.type !== undefined)
{
obj.fileType = this.type;
}
if(this.mime_type !== undefined)
{
obj.fileMimeType = this.mime_type;
}
if(this.content !== undefined)
{
obj.fileFormat = Buffer.isBuffer(this.content) ? 'binary' : 'text';
}
if((this.encoding !== undefined) && (this.encoding !== null))
{
obj.fileEncoding = this.encoding;
}
if(this.git_working_tree !== undefined)
{
obj.gitWorkingTree = this.git_working_tree;
}
if(this.git_dirty !== undefined)
{
obj.gitDirty = this.git_dirty;
}
if(this.git_unmerged !== undefined)
{
obj.gitUnmerged = this.git_unmerged;
}
return obj;
}
}
module.exports = File;