Source: core/insert_update_git_files.js

/*
 * This file is part of PKM (Persistent Knowledge Monitor).
 * 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.
 * 
 * PKM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation.
 * 
 * PKM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with PKM.  If not, see <https://www.gnu.org/licenses/>.
 */

/**
 * Insert/Update files into a Git working tree
 * 
 * @memberof PKM
 * @instance
 * @param {string} dbName - database name
 * @param {string} git_working_tree_directory - Directory of Git working tree
 * @param {Array.<File>} files - files
 * @param {boolean} update - flag to enable/disable replacing files
 * 
 * @return {Promise<Array.<File>>} a promise
 */
function insert_update_git_files(dbName, git_working_tree_directory, files, update)
{
	return new Promise(function(resolve, reject)
	{
		const debug = this.debug;
		let git_file_system = this.get_git_file_system(dbName);
		
		const asyncPool = require('tiny-async-pool');
		const path = require('path');
		
		// Get all the Git working trees
		this.get_git_working_trees(dbName, {}).then((git_working_trees) =>
		{
			// Find the Git working tree by the Git working tree
			let git_working_tree = git_working_trees.find((git_working_tree) => git_working_tree.directory == git_working_tree_directory);
			
			// If found
			if(git_working_tree !== undefined)
			{
				// Check that request is valid and does not conflict
				new Promise((resolve, reject) =>
				{
					let git_working_tree_file_system = this.get_git_working_tree_file_system(dbName, git_working_tree.directory);
					
					asyncPool(1, files, (file) => new Promise((resolve, reject) =>
					{
						// Make the filename relative to Git file system root directory
						const abs_file_path = git_working_tree_file_system.make_abs_path(file.rel_path);
						if(git_working_tree_file_system.check_abs_file_path(abs_file_path))
						{
							file.rel_path = git_file_system.make_rel_path(abs_file_path);
						
							// Check that the file is not in any Git directory
							if(git_working_trees.find((git_working_tree) => file.rel_path.startsWith(git_working_tree.git_directory)) !== undefined)
							{
								reject(this.BadRequest());
								return;
							}
							
							// Look at an existing file or directory
							git_file_system.stat(file.rel_path).then((stats) =>
							{
								// If updating and existing object is a file
								if(update && stats.isFile())
								{
									// accept
									resolve();
								}
								else
								{
									// otherwise reject
									reject(this.Conflict());
								}
							}).catch((err) =>
							{
								resolve();
							});
						}
						else
						{
							reject(this.BadRequest());
						}
					})).then(() =>
					{
						resolve();
					}).catch((err) =>
					{
						reject(this.Error(err));
					});
				}).then(() =>
				{
					asyncPool(1, files, (file) => new Promise((resolve, reject) =>
					{
						// write the file
						git_file_system.writeFile(file).then(() =>
						{
							resolve();
						}).catch((err) =>
						{
							reject(this.Error(err));
						});
					})).then((result) =>
					{
						// job's done
						resolve();
					}).catch((err) =>
					{
						reject(this.Error(err));
					});
				}).catch((err) =>
				{
					reject(this.Error(err));
				});
			}
			else
			{
				reject(this.NotFound());
			}
		}).catch((err) =>
		{
			reject(this.Error(err));
		});
	}.bind(this));
}

exports.insert_update_git_files = insert_update_git_files;