<commit_before>﻿//-----------------------------------------------------------------------
// <copyright file="GoogleDriveFileSystem.cs" company="Fubar Development Junker">
//     Copyright (c) Fubar Development Junker. All rights reserved.
// </copyright>
// <author><NAME></author>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using RestSharp.Portable.Google.Drive;

using File = RestSharp.Portable.Google.Drive.Model.File;

namespace FubarDev.FtpServer.FileSystem.GoogleDrive
{
    internal class GoogleDriveFileSystem : IUnixFileSystem
    {
        private readonly Dictionary<string, BackgroundUpload> _uploads = new Dictionary<string, BackgroundUpload>();

        private readonly SemaphoreSlim _uploadsLock = new SemaphoreSlim(1);

        private bool _disposedValue;

        public GoogleDriveFileSystem(GoogleDriveService service, File rootFolderInfo)
        {
            Service = service;
            RootFolderInfo = rootFolderInfo;
            Root = new GoogleDriveDirectoryEntry(RootFolderInfo, "/", true);
        }

        public GoogleDriveService Service { get; }

        public File RootFolderInfo { get; }

        public StringComparer FileSystemEntryComparer => StringComparer.OrdinalIgnoreCase;

        public IUnixDirectoryEntry Root { get; }

        public async Task<IReadOnlyList<IUnixFileSystemEntry>> GetEntriesAsync(IUnixDirectoryEntry directoryEntry, CancellationToken cancellationToken)
        {
            var dirEntry = (GoogleDriveDirectoryEntry)directoryEntry;
            var entries = await ConvertEntries(
                dirEntry,
                () => Service.GetChildrenAsync(dirEntry.File, cancellationToken),
                cancellationToken);
            return entries;
        }

        public async Task<IUnixFileSystemEntry> GetEntryByNameAsync(IUnixDirectoryEntry directoryEntry, string name, CancellationToken cancellationToken)
        {
            var dirEntry = (GoogleDriveDirectoryEntry)directoryEntry;
            var entries = await ConvertEntries(
                dirEntry,
                () => Service.FindChildByNameAsync(dirEntry.File, name, cancellationToken),
                cancellationToken);
            return entries.FirstOrDefault();
        }

        public async Task<IUnixFileSystemEntry> MoveAsync(IUnixDirectoryEntry parent, IUnixFileSystemEntry source, IUnixDirectoryEntry target, string fileName, CancellationToken cancellationToken)
        {
            var parentEntry = (GoogleDriveDirectoryEntry)parent;
            var targetEntry = (GoogleDriveDirectoryEntry)target;
            var targetName = FileSystemExtensions.CombinePath(targetEntry.FullName, fileName);

            var sourceFileEntry = source as GoogleDriveFileEntry;
            if (sourceFileEntry != null)
            {
                var newFile = await Service.MoveAsync(sourceFileEntry.File, parentEntry.File.Id, targetEntry.File, fileName, cancellationToken);
                return new GoogleDriveFileEntry(newFile, targetName);
            }

            var sourceDirEntry = (GoogleDriveDirectoryEntry)source;
            var newDir = await Service.MoveAsync(sourceDirEntry.File, parentEntry.File.Id, targetEntry.File, fileName, cancellationToken);
            return new GoogleDriveDirectoryEntry(newDir, targetName);
        }

        public async Task UnlinkAsync(IUnixFileSystemEntry entry, CancellationToken cancellationToken)
        {
            var dirEntry = entry as GoogleDriveDirectoryEntry;
            if (dirEntry != null)
            {
                await Service.TrashAsync(dirEntry.File, cancellationToken);
            }
            else
            {
                var fileEntry = (GoogleDriveFileEntry)entry;
                await Service.TrashAsync(fileEntry.File, cancellationToken);
            }
        }

        public async Task<IUnixDirectoryEntry> CreateDirectoryAsync(IUnixDirectoryEntry targetDirectory, string directoryName, CancellationToken cancellationToken)
        {
            var dirEntry = (GoogleDriveDirectoryEntry)targetDirectory;
            var newDir = await Service.CreateDirectoryAsync(dirEntry.File, directoryName, cancellationToken);
            return new GoogleDriveDirectoryEntry(newDir, FileSystemExtensions.CombinePath(dirEntry.FullName, newDir.Title));
        }

        public async Task<Stream> OpenReadAsync(IUnixFileEntry fileEntry, long startPosition, CancellationToken cancellationToken)
        {
            HttpRange range = startPosition != 0 ? new HttpRange("bytes", new HttpRangeItem(startPosition, fileEntry.Size)) : null;
            var fe = (GoogleDriveFileEntry)fileEntry;
            var response = await Service.GetDownloadResponseAsync(fe.File, range, cancellationToken);
            return new GoogleDriveDownloadStream(response, startPosition, fe.Size);
        }

        public Task<IBackgroundTransfer> AppendAsync(IUnixFileEntry fileEntry, long? startPosition, Stream data, CancellationToken cancellationToken)
        {
            throw new NotSupportedException();
        }

        public async Task<IBackgroundTransfer> CreateAsync(IUnixDirectoryEntry targetDirectory, string fileName, Stream data, CancellationToken cancellationToken)
        {
            var targetEntry = (GoogleDriveDirectoryEntry)targetDirectory;
            var newFileEntry = await Service.CreateItemAsync(targetEntry.File, fileName, "application/octet-stream", cancellationToken);
            var tempFileName = Path.GetTempFileName();
            long fileSize;
            using (var temp = new FileStream(tempFileName, FileMode.Truncate))
            {
                await data.CopyToAsync(temp, 4096, cancellationToken);
                fileSize = temp.Position;
            }
            var fullPath = FileSystemExtensions.CombinePath(targetEntry.FullName, fileName);
            var backgroundUploads = new BackgroundUpload(fullPath, newFileEntry, tempFileName, this, fileSize);
            await _uploadsLock.WaitAsync(cancellationToken);
            try<commit_msg>Set default mime type for newly created file<commit_after>﻿//-----------------------------------------------------------------------
// <copyright file="GoogleDriveFileSystem.cs" company="Fubar Development Junker">
//     Copyright (c) Fubar Development Junker. All rights reserved.
// </copyright>
// <author><NAME></author>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

using RestSharp.Portable.Google.Drive;

using File = RestSharp.Portable.Google.Drive.Model.File;

namespace FubarDev.FtpServer.FileSystem.GoogleDrive
{
    internal class GoogleDriveFileSystem : IUnixFileSystem
    {
        private readonly Dictionary<string, BackgroundUpload> _uploads = new Dictionary<string, BackgroundUpload>();

        private readonly SemaphoreSlim _uploadsLock = new SemaphoreSlim(1);

        private bool _disposedValue;

        public GoogleDriveFileSystem(GoogleDriveService service, File rootFolderInfo)
        {
            Service = service;
            RootFolderInfo = rootFolderInfo;
            Root = new GoogleDriveDirectoryEntry(RootFolderInfo, "/", true);
        }

        public GoogleDriveService Service { get; }

        public File RootFolderInfo { get; }

        public StringComparer FileSystemEntryComparer => StringComparer.OrdinalIgnoreCase;

        public IUnixDirectoryEntry Root { get; }

        public async Task<IReadOnlyList<IUnixFileSystemEntry>> GetEntriesAsync(IUnixDirectoryEntry directoryEntry, CancellationToken cancellationToken)
        {
            var dirEntry = (GoogleDriveDirectoryEntry)directoryEntry;
            var entries = await ConvertEntries(
                dirEntry,
                () => Service.GetChildrenAsync(dirEntry.File, cancellationToken),
                cancellationToken);
            return entries;
        }

        public async Task<IUnixFileSystemEntry> GetEntryByNameAsync(IUnixDirectoryEntry directoryEntry, string name, CancellationToken cancellationToken)
        {
            var dirEntry = (GoogleDriveDirectoryEntry)directoryEntry;
            var entries = await ConvertEntries(
                dirEntry,
                () => Service.FindChildByNameAsync(dirEntry.File, name, cancellationToken),
                cancellationToken);
            return entries.FirstOrDefault();
        }

        public async Task<IUnixFileSystemEntry> MoveAsync(IUnixDirectoryEntry parent, IUnixFileSystemEntry source, IUnixDirectoryEntry target, string fileName, CancellationToken cancellationToken)
        {
            var parentEntry = (GoogleDriveDirectoryEntry)parent;
            var targetEntry = (GoogleDriveDirectoryEntry)target;
            var targetName = FileSystemExtensions.CombinePath(targetEntry.FullName, fileName);

            var sourceFileEntry = source as GoogleDriveFileEntry;
            if (sourceFileEntry != null)
            {
                var newFile = await Service.MoveAsync(sourceFileEntry.File, parentEntry.File.Id, targetEntry.File, fileName, cancellationToken);
                return new GoogleDriveFileEntry(newFile, targetName);
            }

            var sourceDirEntry = (GoogleDriveDirectoryEntry)source;
            var newDir = await Service.MoveAsync(sourceDirEntry.File, parentEntry.File.Id, targetEntry.File, fileName, cancellationToken);
            return new GoogleDriveDirectoryEntry(newDir, targetName);
        }

        public async Task UnlinkAsync(IUnixFileSystemEntry entry, CancellationToken cancellationToken)
        {
            var dirEntry = entry as GoogleDriveDirectoryEntry;
            if (dirEntry != null)
            {
                await Service.TrashAsync(dirEntry.File, cancellationToken);
            }
            else
            {
                var fileEntry = (GoogleDriveFileEntry)entry;
                await Service.TrashAsync(fileEntry.File, cancellationToken);
            }
        }

        public async Task<IUnixDirectoryEntry> CreateDirectoryAsync(IUnixDirectoryEntry targetDirectory, string directoryName, CancellationToken cancellationToken)
        {
            var dirEntry = (GoogleDriveDirectoryEntry)targetDirectory;
            var newDir = await Service.CreateDirectoryAsync(dirEntry.File, directoryName, cancellationToken);
            return new GoogleDriveDirectoryEntry(newDir, FileSystemExtensions.CombinePath(dirEntry.FullName, newDir.Title));
        }

        public async Task<Stream> OpenReadAsync(IUnixFileEntry fileEntry, long startPosition, CancellationToken cancellationToken)
        {
            HttpRange range = startPosition != 0 ? new HttpRange("bytes", new HttpRangeItem(startPosition, fileEntry.Size)) : null;
            var fe = (GoogleDriveFileEntry)fileEntry;
            var response = await Service.GetDownloadResponseAsync(fe.File, range, cancellationToken);
            return new GoogleDriveDownloadStream(response, startPosition, fe.Size);
        }

        public Task<IBackgroundTransfer> AppendAsync(IUnixFileEntry fileEntry, long? startPosition, Stream data, CancellationToken cancellationToken)
        {
            throw new NotSupportedException();
        }

        public async Task<IBackgroundTransfer> CreateAsync(IUnixDirectoryEntry targetDirectory, string fileName, Stream data, CancellationToken cancellationToken)
        {
            var targetEntry = (GoogleDriveDirectoryEntry)targetDirectory;
            var newFileEntry = await Service.CreateItemAsync(targetEntry.File, fileName, cancellationToken);
            var tempFileName = Path.GetTempFileName();
            long fileSize;
            using (var temp = new FileStream(tempFileName, FileMode.Truncate))
            {
                await data.CopyToAsync(temp, 4096, cancellationToken);
                fileSize = temp.Position;
            }
            var fullPath = FileSystemExtensions.CombinePath(targetEntry.FullName, fileName);
            var backgroundUploads = new BackgroundUpload(fullPath, newFileEntry, tempFileName, this, fileSize);
            await _uploadsLock.WaitAsync(cancellationToken);
            try
{'fraction_non_alphanumeric': 0.09193639518928082, 'fraction_numerical': 0.0009686011784647671, 'mean_word_length': 2.68640285629277, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5107300', 'n_tokens_mistral': 2927, 'n_tokens_neox': 2884, 'n_words': 671}