checkpoint

This commit is contained in:
2020-04-30 17:27:50 -04:00
parent 9bc522180d
commit 9aa367e9f5
16 changed files with 176 additions and 98 deletions

View File

@@ -13,7 +13,7 @@ namespace Alpm.Tests
public void TestLocalDB()
{
using var localDB = _handle.LocalDB;
Assert.True(localDB.CachePackageCache.Count() > 15);
Assert.True(localDB.PackageCache.Count() > 15);
}
[Fact]

View File

@@ -5,29 +5,5 @@ namespace Foodsoft.Alpm
public static class API
{
public static readonly string Version = alpm.alpm_version();
internal static void WrapError(SafeAlpmHandle h, Func<int> f)
{
var err = f();
if (err != 0)
{
throw new AlpmException(h);
}
}
/*
* Handles the pattern where <0 is exceptional, but 1 is some "false"
* condition.
*/
internal static bool WrapErrorBool(SafeAlpmHandle h, Func<int> f)
{
var err = f();
if (err < 0)
{
throw new AlpmException(h);
}
return err == 0;
}
}
}

View File

@@ -3,11 +3,15 @@ using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
public struct Backup
public readonly struct Backup : IEquatable<Backup>
{
public string Name { get; }
public string Hash { get; }
public bool Equals(Backup other) => Name == other.Name && Hash == other.Hash;
public override bool Equals(object? obj) => obj is Backup other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Name, Hash);
[StructLayout(LayoutKind.Sequential)]
private readonly unsafe struct NativeBackup
{

View File

@@ -1,10 +1,15 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
public class CachePackageList : IPackageList<CachePackage>, ICollection<CachePackage>
{
private readonly SafeDatabaseHandle _parentHandle;
@@ -18,6 +23,7 @@ namespace Foodsoft.Alpm
_db = db;
}
[PrePrepareMethod]
public IEnumerator<CachePackage> GetEnumerator()
{
var release = false;
@@ -27,10 +33,10 @@ namespace Foodsoft.Alpm
{
_parentHandle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_parentHandle.GetType().FullName);
for (var list = _listPtr; list != IntPtr.Zero; list = Wrapper.ListNext(list))
for (var list = _listPtr; list != IntPtr.Zero; list = Detail.ListNext(list))
{
yield return new CachePackage(
new SafeCachePackageHandle(Wrapper.ListData(list), _parentHandle), _db);
new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db);
}
}
finally
@@ -51,7 +57,7 @@ namespace Foodsoft.Alpm
return _parentHandle.UseHandle(_listPtr, (list) =>
{
for (; list != IntPtr.Zero; list = Wrapper.ListNext(list))
for (; list != IntPtr.Zero; list = Detail.ListNext(list))
{
if (name == alpm.alpm_pkg_get_name(list))
return true;
@@ -65,15 +71,16 @@ namespace Foodsoft.Alpm
{
_parentHandle.UseHandle(_listPtr, (list) =>
{
for (; list != IntPtr.Zero; list = Wrapper.ListNext(list))
for (; list != IntPtr.Zero; list = Detail.ListNext(list))
{
array[arrayIndex++] = new CachePackage(
new SafeCachePackageHandle(Wrapper.ListData(list), _parentHandle), _db);
new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db);
}
return 0;
});
}
public CachePackage? FindSatisfier(string depString)
{
return _parentHandle.UseHandle(_listPtr, (list) =>

View File

@@ -7,6 +7,16 @@ namespace Foodsoft.Alpm
{
public sealed class Database : IDisposable
{
[Flags]
public enum UsageFlags
{
Sync = 1,
Search = (1 << 1),
Install = (1 << 2),
Upgrade = (1 << 3),
All = (1 << 4) - 1,
}
private readonly SafeDatabaseHandle _handle;
internal Database(SafeDatabaseHandle handle) => _handle = handle;
@@ -14,10 +24,10 @@ namespace Foodsoft.Alpm
public void Unregister() => _handle.Close();
public void AddServer(string url) =>
API.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url));
Detail.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url));
public bool RemoveServer(string url) =>
API.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url));
Detail.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url));
// FIXME: This is "bug correct", but probably dumb to do it this way, instead just call add_server
// like all the stuff in handle.
@@ -85,7 +95,7 @@ namespace Foodsoft.Alpm
return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this);
}
public CachePackageList CachePackageCache
public CachePackageList PackageCache
{
get
{
@@ -96,6 +106,13 @@ namespace Foodsoft.Alpm
}
}
public CachePackageList Search()
{
}
public UsageFlags Usage => Detail.WrapError<UsageFlags, SafeDatabaseHandle>(_handle.SafeAlpmHandle, _handle, alpm.alpm_db_get_usage);
public void Dispose()
{
_handle.Dispose();

View File

@@ -1,10 +1,11 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
public class Depend
public class Depend : IEquatable<Depend>
{
public enum ModType
{
@@ -22,6 +23,13 @@ namespace Foodsoft.Alpm
public ulong NameHash { get; }
public ModType Mod { get; }
public override bool Equals(object? obj) => (obj is Depend other) && this.Equals(other);
public bool Equals(Depend? other) => !ReferenceEquals(other, null) && ReferenceEquals(this, other) &&
Name == other.Name && Version == other.Version && Mod == other.Mod;
public override int GetHashCode() => HashCode.Combine(Name, Version, (int) Mod);
[StructLayout(LayoutKind.Sequential)]
private readonly unsafe struct NativeDepend
{
@@ -41,6 +49,5 @@ namespace Foodsoft.Alpm
NameHash = native->name_hash;
Mod = native->mod;
}
}
}

View File

@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
internal static class Wrapper
internal static class Detail
{
internal static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next;
internal static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data;
@@ -41,5 +41,31 @@ namespace Foodsoft.Alpm
}
}
internal static void WrapError(SafeAlpmHandle alpmHandle, Func<int> f)
{
var err = f();
if (err != 0)
throw new AlpmException(alpmHandle);
}
internal delegate int OutFunc<T, in THandle>(THandle handle, out T result);
internal static T WrapError<T, THandle>(SafeAlpmHandle alpmHandle, THandle handle, OutFunc<T, THandle> f)
{
var err = f(handle, out var result);
if (err != 0)
throw new AlpmException(alpmHandle);
return result;
}
internal static bool WrapErrorBool(SafeAlpmHandle h, Func<int> f)
{
var err = f();
if (err < 0)
{
throw new AlpmException(h);
}
return err == 0;
}
}
}

View File

@@ -50,9 +50,9 @@ namespace Foodsoft.Alpm
{
_handle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_handle.GetType().FullName);
for (var list = _getItems(_handle); list != IntPtr.Zero; list = Wrapper.ListNext(list))
for (var list = _getItems(_handle); list != IntPtr.Zero; list = Detail.ListNext(list))
{
yield return _getElement(Wrapper.ListData(list));
yield return _getElement(Detail.ListData(list));
}
}
finally
@@ -87,9 +87,9 @@ namespace Foodsoft.Alpm
var comparer = EqualityComparer<TElement>.Default;
return handle.UseHandle((_) =>
{
for (var list = getItems(handle); list != IntPtr.Zero; list = Wrapper.ListNext(list))
for (var list = getItems(handle); list != IntPtr.Zero; list = Detail.ListNext(list))
{
if (comparer.Equals(item, getElement(Wrapper.ListData(list))))
if (comparer.Equals(item, getElement(Detail.ListData(list))))
return true;
}
@@ -105,9 +105,9 @@ namespace Foodsoft.Alpm
var handle = _handle;
handle.UseHandle((_) =>
{
for (var list = getItems(handle); list != IntPtr.Zero; list = Wrapper.ListNext(list))
for (var list = getItems(handle); list != IntPtr.Zero; list = Detail.ListNext(list))
{
array[arrayIndex++] = getElement(Wrapper.ListData(list));
array[arrayIndex++] = getElement(Detail.ListData(list));
}
return arrayIndex;

View File

@@ -2,6 +2,15 @@ using System;
namespace Foodsoft.Alpm
{
[Flags]
public enum LogLevel
{
Error = 1,
Warning = (1 << 1),
Debug = (1 << 2),
Function = (1 << 3)
}
[Flags]
public enum SigLevel
{

48
Alpm/ExtensionMethods.cs Normal file
View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
namespace Foodsoft.Alpm
{
public static class ExtensionMethods
{
[PrePrepareMethod]
public static Package? FindSatisfier(this IEnumerable<Package> pkgList, string depString)
{
var refs = new Dictionary<IntPtr, Package?>(10);
var listPtr = IntPtr.Zero;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
foreach (var pkg in pkgList)
{
var release = false;
var handle = pkg.Handle;
var pkgPtr = handle.DangerousGetHandle();
refs.Add(pkgPtr, null);
handle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(handle.GetType().FullName);
refs[pkgPtr] = pkg;
listPtr = alpm.alpm_list_add(listPtr, handle.DangerousGetHandle());
}
var foundPtr = alpm.alpm_find_satisfier(listPtr, depString);
return foundPtr != IntPtr.Zero
? refs[foundPtr]
: null;
}
finally
{
alpm.alpm_list_free(listPtr);
foreach (var pkg in refs.Values)
{
pkg?.Handle.DangerousRelease();
}
}
}
}
}

View File

@@ -39,13 +39,13 @@ namespace Foodsoft.Alpm
public Database RegisterSyncDB(string treename, SigLevel sigLevel = 0) =>
ToDatabase(alpm.alpm_register_syncdb(_handle, treename, sigLevel));
public void AddCacheDir(string dir) => API.WrapError(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir));
public bool RemoveCacheDir(string dir) => API.WrapErrorBool(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir));
public void AddCacheDir(string dir) => Detail.WrapError(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir));
public bool RemoveCacheDir(string dir) => Detail.WrapErrorBool(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir));
public ICollection<string> CacheDirs
{
get =>
EnumerableWrapper.Create(_handle, alpm.alpm_option_get_cachedirs);
set => Wrapper.SetStringCollection(value, _handle, (s) => alpm.alpm_option_add_cachedir(_handle, s));
set => Detail.SetStringCollection(value, _handle, (s) => alpm.alpm_option_add_cachedir(_handle, s));
}
public bool ShouldIgnorePackage(Package pkg) => alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0;

View File

@@ -44,17 +44,17 @@ namespace Foodsoft.Alpm
public long Size { get; }
public long InstalledSize { get; }
public InstallReason InstallReason { get; }
public ICollection<string> Licenses { get; }
public ICollection<string> Groups { get; }
public ICollection<Depend> Depends { get; }
public ICollection<Depend> OptDepends { get; }
public ICollection<Depend> CheckDepends { get; }
public ICollection<Depend> MakeDepends { get; }
public ICollection<Depend> Conflicts { get; }
public ICollection<Depend> Provides { get; }
public ICollection<Depend> Replaces { get; }
public IEnumerable<string> Licenses { get; }
public IEnumerable<string> Groups { get; }
public IEnumerable<Depend> Depends { get; }
public IEnumerable<Depend> OptDepends { get; }
public IEnumerable<Depend> CheckDepends { get; }
public IEnumerable<Depend> MakeDepends { get; }
public IEnumerable<Depend> Conflicts { get; }
public IEnumerable<Depend> Provides { get; }
public IEnumerable<Depend> Replaces { get; }
public IReadOnlyList<File> Files { get; }
public ICollection<Backup> Backup { get; }
public IEnumerable<Backup> Backup { get; }
public string Base64Signature { get; }
public ValidationType Validation { get; }
public bool HasScriptlet { get; }

View File

@@ -102,28 +102,8 @@ namespace Foodsoft.Alpm
SIGVALIDITY_UNKNOWN
}
/** Dependency */
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct alpm_depend_t
{
string name;
string version;
string desc;
public ulong name_hash;
public alpm_depmod_t mod;
}
[StructLayout(LayoutKind.Sequential)]
public struct AlpmDependPtr
{
private IntPtr ptr;
public alpm_depend_t Unmarshal()
{
return Marshal.PtrToStructure<alpm_depend_t>(ptr);
}
}
#if JUNK_INCLUDE
/** Missing dependency */
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct alpm_depmissing_t
@@ -146,6 +126,7 @@ namespace Foodsoft.Alpm
public string package2;
public AlpmDependPtr reason;
}
#endif
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
/** File conflict */

View File

@@ -30,21 +30,21 @@ namespace Foodsoft.Alpm
public long Size => alpm.alpm_pkg_get_size(Handle);
public long InstalledSize => alpm.alpm_pkg_get_isize(Handle);
public InstallReason InstallReason => alpm.alpm_pkg_get_reason(Handle);
public ICollection<string> Licenses =>
public IEnumerable<string> Licenses =>
EnumerableWrapper.Create(Handle, alpm.alpm_pkg_get_licenses);
public ICollection<string> Groups => EnumerableWrapper.Create(Handle, alpm.alpm_pkg_get_groups);
public ICollection<Depend> Depends => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_depends);
public ICollection<Depend> OptDepends =>
public IEnumerable<string> Groups => EnumerableWrapper.Create(Handle, alpm.alpm_pkg_get_groups);
public IEnumerable<Depend> Depends => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_depends);
public IEnumerable<Depend> OptDepends =>
EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_optdepends);
public ICollection<Depend> CheckDepends =>
public IEnumerable<Depend> CheckDepends =>
EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_checkdepends);
public ICollection<Depend> MakeDepends =>
public IEnumerable<Depend> MakeDepends =>
EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_makedepends);
public ICollection<Depend> Conflicts => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_conflicts);
public ICollection<Depend> Provides => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_provides);
public ICollection<Depend> Replaces => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_replaces);
public IEnumerable<Depend> Conflicts => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_conflicts);
public IEnumerable<Depend> Provides => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_provides);
public IEnumerable<Depend> Replaces => EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_replaces);
public IReadOnlyList<File> Files => new FileList(Handle, alpm.alpm_pkg_get_files(Handle));
public ICollection<Backup> Backup => EnumerableWrapper.CreateForBackup(Handle, alpm.alpm_pkg_get_backup);
public IEnumerable<Backup> Backup => EnumerableWrapper.CreateForBackup(Handle, alpm.alpm_pkg_get_backup);
public string Base64Signature => alpm.alpm_pkg_get_base64_sig(Handle);
public ValidationType Validation => alpm.alpm_pkg_get_validation(Handle);
public bool HasScriptlet => alpm.alpm_pkg_has_scriptlet(Handle);

View File

@@ -251,6 +251,12 @@ namespace Foodsoft.Alpm
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
string url);
[DllImport(nameof(alpm))]
public static extern int alpm_db_get_usage(SafeDatabaseHandle db, out Database.UsageFlags usage);
[DllImport(nameof(alpm))]
public static extern int alpm_db_set_usage(SafeDatabaseHandle db, Database.UsageFlags usage);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_pkg_get_pkg(SafeDatabaseHandle db,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]

View File

@@ -31,7 +31,7 @@ namespace Samples
using var h = new Handle("/", "/var/lib/pacman");
using var db = h.LocalDB;
foreach (var pkg in db.CachePackageCache)
foreach (var pkg in db.PackageCache)
using (pkg)
{
Console.WriteLine($"Size: {pkg.DownloadSize}");
@@ -57,13 +57,10 @@ namespace Samples
using var h = new Handle("/", "/var/lib/pacman");
using var db = h.RegisterSyncDB("core");
db.Servers = new[] {"http://www.google.com"};
db.Update(true);
foreach (var pkg in db.CachePackageCache)
using (pkg)
{
Console.WriteLine("{0} {1} {2}", pkg.Name, pkg.Version, pkg.Description);
}
using var pkg = db.PackageCache.FindSatisfier("gcc=9.3.0-1");
Console.WriteLine($"{pkg?.Name} {pkg?.Version}");
return 0;
}