From 64f7dd4b7d4fd5ee6e79094e2147c772b73db397 Mon Sep 17 00:00:00 2001 From: "John K. Luebs" Date: Wed, 29 Apr 2020 13:10:17 -0400 Subject: [PATCH] checkpoint --- .gitignore | 4 +- .../.idea/.gitignore | 6 +- .../.idea/encodings.xml | 0 .../.idea/indexLayout.xml | 0 .../.idea/misc.xml | 0 .../.idea/vcs.xml | 0 .../riderModule.iml | 0 .../.idea/.idea.DotNetAplm.dir.iml | 8 --- .idea/.idea.nalpm.dir/.idea/.gitignore | 13 ----- .../.idea.nalpm.dir/.idea/.idea.nalpm.dir.iml | 8 --- .idea/.idea.nalpm.dir/.idea/encodings.xml | 4 -- .idea/.idea.nalpm.dir/.idea/indexLayout.xml | 8 --- .idea/.idea.nalpm.dir/.idea/misc.xml | 6 -- .idea/.idea.nalpm.dir/.idea/vcs.xml | 6 -- .idea/.idea.nalpm.dir/riderModule.iml | 7 --- API.cs | 18 ------ Alpm/API.cs | 33 +++++++++++ DotNetAlpm.csproj => Alpm/Alpm.csproj | 2 +- Backup.cs => Alpm/Backup.cs | 0 CachePackage.cs => Alpm/CachePackage.cs | 0 .../CollectionWrapper`2.cs | 2 + Database.cs => Alpm/Database.cs | 55 +++++++++++-------- Depend.cs => Alpm/Depend.cs | 0 Alpm/EnumerableWrapper`3.cs | 44 +++++++++++++++ ErrNo.cs => Alpm/ErrNo.cs | 0 Exception.cs => Alpm/Exception.cs | 0 File.cs => Alpm/File.cs | 0 FileList.cs => Alpm/FileList.cs | 0 Handle.cs => Alpm/Handle.cs | 0 .../IAlpmItemsAccessor`1.cs | 0 Alpm/IItemsReader`2.cs | 12 ++++ IPackageData.cs => Alpm/IPackageData.cs | 4 +- Junk.cs => Alpm/Junk.cs | 0 Package.cs => Alpm/Package.cs | 13 +++-- Alpm/PackageList.cs | 51 +++++++++++++++++ SafeAlpmHandle.cs => Alpm/SafeAlpmHandle.cs | 0 .../SafeCachePackageHandle.cs | 14 ++--- .../SafeDatabaseHandle.cs | 3 +- SafeListHandle.cs => Alpm/SafeListHandle`1.cs | 21 ++++--- .../SafePackageHandle.cs | 0 UTF8InMarshaler.cs => Alpm/UTF8InMarshaler.cs | 1 - .../UTF8OutMarshaler.cs | 0 Alpm/Wrapper.cs | 10 ++++ alpm.cs => Alpm/alpm.cs | 4 +- AlpmOld.cs | 21 ------- DotNetAlpm.sln | 22 ++++++++ DotNetAlpm.sln.DotSettings | 2 + Folder.DotSettings | 12 ---- IReadOnlyItemsAccessor`1.cs | 11 ---- Program.cs | 27 --------- ReadOnlyCollectionWrapper`2.cs | 47 ---------------- Samples/Program.cs | 39 +++++++++++++ Samples/Samples.csproj | 12 ++++ Wrapper.cs | 7 --- 54 files changed, 294 insertions(+), 263 deletions(-) rename .idea/{.idea.DotNetAplm.dir => .idea.DotNetAlpm}/.idea/.gitignore (92%) rename .idea/{.idea.DotNetAplm.dir => .idea.DotNetAlpm}/.idea/encodings.xml (100%) rename .idea/{.idea.DotNetAplm.dir => .idea.DotNetAlpm}/.idea/indexLayout.xml (100%) rename .idea/{.idea.DotNetAplm.dir => .idea.DotNetAlpm}/.idea/misc.xml (100%) rename .idea/{.idea.DotNetAplm.dir => .idea.DotNetAlpm}/.idea/vcs.xml (100%) rename .idea/{.idea.DotNetAplm.dir => .idea.DotNetAlpm}/riderModule.iml (100%) delete mode 100644 .idea/.idea.DotNetAplm.dir/.idea/.idea.DotNetAplm.dir.iml delete mode 100644 .idea/.idea.nalpm.dir/.idea/.gitignore delete mode 100644 .idea/.idea.nalpm.dir/.idea/.idea.nalpm.dir.iml delete mode 100644 .idea/.idea.nalpm.dir/.idea/encodings.xml delete mode 100644 .idea/.idea.nalpm.dir/.idea/indexLayout.xml delete mode 100644 .idea/.idea.nalpm.dir/.idea/misc.xml delete mode 100644 .idea/.idea.nalpm.dir/.idea/vcs.xml delete mode 100644 .idea/.idea.nalpm.dir/riderModule.iml delete mode 100644 API.cs create mode 100644 Alpm/API.cs rename DotNetAlpm.csproj => Alpm/Alpm.csproj (84%) rename Backup.cs => Alpm/Backup.cs (100%) rename CachePackage.cs => Alpm/CachePackage.cs (100%) rename CollectionWrapper`2.cs => Alpm/CollectionWrapper`2.cs (95%) rename Database.cs => Alpm/Database.cs (60%) rename Depend.cs => Alpm/Depend.cs (100%) create mode 100644 Alpm/EnumerableWrapper`3.cs rename ErrNo.cs => Alpm/ErrNo.cs (100%) rename Exception.cs => Alpm/Exception.cs (100%) rename File.cs => Alpm/File.cs (100%) rename FileList.cs => Alpm/FileList.cs (100%) rename Handle.cs => Alpm/Handle.cs (100%) rename IAlpmItemsAccessor`1.cs => Alpm/IAlpmItemsAccessor`1.cs (100%) create mode 100644 Alpm/IItemsReader`2.cs rename IPackageData.cs => Alpm/IPackageData.cs (95%) rename Junk.cs => Alpm/Junk.cs (100%) rename Package.cs => Alpm/Package.cs (92%) create mode 100644 Alpm/PackageList.cs rename SafeAlpmHandle.cs => Alpm/SafeAlpmHandle.cs (100%) rename SafeCachePackageHandle.cs => Alpm/SafeCachePackageHandle.cs (73%) rename SafeDatabaseHandle.cs => Alpm/SafeDatabaseHandle.cs (94%) rename SafeListHandle.cs => Alpm/SafeListHandle`1.cs (70%) rename SafePackageHandle.cs => Alpm/SafePackageHandle.cs (100%) rename UTF8InMarshaler.cs => Alpm/UTF8InMarshaler.cs (99%) rename UTF8OutMarshaler.cs => Alpm/UTF8OutMarshaler.cs (100%) create mode 100644 Alpm/Wrapper.cs rename alpm.cs => Alpm/alpm.cs (98%) delete mode 100644 AlpmOld.cs create mode 100644 DotNetAlpm.sln create mode 100644 DotNetAlpm.sln.DotSettings delete mode 100644 Folder.DotSettings delete mode 100644 IReadOnlyItemsAccessor`1.cs delete mode 100644 Program.cs delete mode 100644 ReadOnlyCollectionWrapper`2.cs create mode 100644 Samples/Program.cs create mode 100644 Samples/Samples.csproj delete mode 100644 Wrapper.cs diff --git a/.gitignore b/.gitignore index 4ded7c4..cd42ee3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -/bin/ -/obj/ +bin/ +obj/ diff --git a/.idea/.idea.DotNetAplm.dir/.idea/.gitignore b/.idea/.idea.DotNetAlpm/.idea/.gitignore similarity index 92% rename from .idea/.idea.DotNetAplm.dir/.idea/.gitignore rename to .idea/.idea.DotNetAlpm/.idea/.gitignore index 4e0d79f..4e4a45c 100644 --- a/.idea/.idea.DotNetAplm.dir/.idea/.gitignore +++ b/.idea/.idea.DotNetAlpm/.idea/.gitignore @@ -2,10 +2,10 @@ /shelf/ /workspace.xml # Rider ignored files -/contentModel.xml -/.idea.DotNetAplm.iml -/projectSettingsUpdater.xml /modules.xml +/contentModel.xml +/projectSettingsUpdater.xml +/.idea.DotNetAlpm.iml # Datasource local storage ignored files /dataSources/ /dataSources.local.xml diff --git a/.idea/.idea.DotNetAplm.dir/.idea/encodings.xml b/.idea/.idea.DotNetAlpm/.idea/encodings.xml similarity index 100% rename from .idea/.idea.DotNetAplm.dir/.idea/encodings.xml rename to .idea/.idea.DotNetAlpm/.idea/encodings.xml diff --git a/.idea/.idea.DotNetAplm.dir/.idea/indexLayout.xml b/.idea/.idea.DotNetAlpm/.idea/indexLayout.xml similarity index 100% rename from .idea/.idea.DotNetAplm.dir/.idea/indexLayout.xml rename to .idea/.idea.DotNetAlpm/.idea/indexLayout.xml diff --git a/.idea/.idea.DotNetAplm.dir/.idea/misc.xml b/.idea/.idea.DotNetAlpm/.idea/misc.xml similarity index 100% rename from .idea/.idea.DotNetAplm.dir/.idea/misc.xml rename to .idea/.idea.DotNetAlpm/.idea/misc.xml diff --git a/.idea/.idea.DotNetAplm.dir/.idea/vcs.xml b/.idea/.idea.DotNetAlpm/.idea/vcs.xml similarity index 100% rename from .idea/.idea.DotNetAplm.dir/.idea/vcs.xml rename to .idea/.idea.DotNetAlpm/.idea/vcs.xml diff --git a/.idea/.idea.DotNetAplm.dir/riderModule.iml b/.idea/.idea.DotNetAlpm/riderModule.iml similarity index 100% rename from .idea/.idea.DotNetAplm.dir/riderModule.iml rename to .idea/.idea.DotNetAlpm/riderModule.iml diff --git a/.idea/.idea.DotNetAplm.dir/.idea/.idea.DotNetAplm.dir.iml b/.idea/.idea.DotNetAplm.dir/.idea/.idea.DotNetAplm.dir.iml deleted file mode 100644 index e6bc2ca..0000000 --- a/.idea/.idea.DotNetAplm.dir/.idea/.idea.DotNetAplm.dir.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/.idea.nalpm.dir/.idea/.gitignore b/.idea/.idea.nalpm.dir/.idea/.gitignore deleted file mode 100644 index 087e243..0000000 --- a/.idea/.idea.nalpm.dir/.idea/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Rider ignored files -/modules.xml -/contentModel.xml -/projectSettingsUpdater.xml -/.idea.nalpm.iml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/.idea.nalpm.dir/.idea/.idea.nalpm.dir.iml b/.idea/.idea.nalpm.dir/.idea/.idea.nalpm.dir.iml deleted file mode 100644 index e6bc2ca..0000000 --- a/.idea/.idea.nalpm.dir/.idea/.idea.nalpm.dir.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/.idea.nalpm.dir/.idea/encodings.xml b/.idea/.idea.nalpm.dir/.idea/encodings.xml deleted file mode 100644 index df87cf9..0000000 --- a/.idea/.idea.nalpm.dir/.idea/encodings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/.idea.nalpm.dir/.idea/indexLayout.xml b/.idea/.idea.nalpm.dir/.idea/indexLayout.xml deleted file mode 100644 index 27ba142..0000000 --- a/.idea/.idea.nalpm.dir/.idea/indexLayout.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/.idea.nalpm.dir/.idea/misc.xml b/.idea/.idea.nalpm.dir/.idea/misc.xml deleted file mode 100644 index 28a804d..0000000 --- a/.idea/.idea.nalpm.dir/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/.idea.nalpm.dir/.idea/vcs.xml b/.idea/.idea.nalpm.dir/.idea/vcs.xml deleted file mode 100644 index 6c0b863..0000000 --- a/.idea/.idea.nalpm.dir/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/.idea.nalpm.dir/riderModule.iml b/.idea/.idea.nalpm.dir/riderModule.iml deleted file mode 100644 index 1a4e0d9..0000000 --- a/.idea/.idea.nalpm.dir/riderModule.iml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/API.cs b/API.cs deleted file mode 100644 index 62c1f54..0000000 --- a/API.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Foodsoft.Alpm -{ - public static class API - { - public static readonly string Version = alpm.alpm_version(); - - internal static void WrapError(SafeAlpmHandle h, Func f) - { - var err = f(); - if (err != 0) - { - throw new Exception(alpm.alpm_errno(h)); - } - } - } -} \ No newline at end of file diff --git a/Alpm/API.cs b/Alpm/API.cs new file mode 100644 index 0000000..1d1cb3b --- /dev/null +++ b/Alpm/API.cs @@ -0,0 +1,33 @@ +using System; + +namespace Foodsoft.Alpm +{ + public static class API + { + public static readonly string Version = alpm.alpm_version(); + + internal static void WrapError(SafeAlpmHandle h, Func f) + { + var err = f(); + if (err != 0) + { + throw new Exception(alpm.alpm_errno(h)); + } + } + + /* + * Handles the pattern where <0 is exceptional, but 1 is some "false" + * condition. + */ + internal static bool WrapErrorBool(SafeAlpmHandle h, Func f) + { + var err = f(); + if (err < 0) + { + throw new Exception(alpm.alpm_errno(h)); + } + return err == 0; + } + + } +} \ No newline at end of file diff --git a/DotNetAlpm.csproj b/Alpm/Alpm.csproj similarity index 84% rename from DotNetAlpm.csproj rename to Alpm/Alpm.csproj index 928485e..b84ea79 100644 --- a/DotNetAlpm.csproj +++ b/Alpm/Alpm.csproj @@ -1,7 +1,7 @@ - Exe + Module netcoreapp3.1 true enable diff --git a/Backup.cs b/Alpm/Backup.cs similarity index 100% rename from Backup.cs rename to Alpm/Backup.cs diff --git a/CachePackage.cs b/Alpm/CachePackage.cs similarity index 100% rename from CachePackage.cs rename to Alpm/CachePackage.cs diff --git a/CollectionWrapper`2.cs b/Alpm/CollectionWrapper`2.cs similarity index 95% rename from CollectionWrapper`2.cs rename to Alpm/CollectionWrapper`2.cs index 1c7f7a3..a62b87f 100644 --- a/CollectionWrapper`2.cs +++ b/Alpm/CollectionWrapper`2.cs @@ -3,6 +3,8 @@ using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; +// FIXME: This is increasing the ref-count on AlpmHandle all the time, so this is NOT correct for database handles, +// or other handles that have a dispose that is not a no-op. namespace Foodsoft.Alpm { internal class CollectionWrapper : ICollection where TImpl : struct, diff --git a/Database.cs b/Alpm/Database.cs similarity index 60% rename from Database.cs rename to Alpm/Database.cs index a494cc2..033aff1 100644 --- a/Database.cs +++ b/Alpm/Database.cs @@ -10,27 +10,38 @@ namespace Foodsoft.Alpm internal Database(SafeDatabaseHandle handle) => _handle = handle; - private readonly struct ServersAccessor : IItemsAccessor + public void Unregister() { - private readonly SafeDatabaseHandle _handle; + try + { + API.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_unregister(_handle)); + } + finally + { + _handle.Close(); + } + } + + private readonly struct ServersAccessor : IItemsReader + { internal ServersAccessor(SafeDatabaseHandle handle) { - _handle = handle; + Handle = handle; } - public SafeAlpmHandle SafeAlpmHandle => _handle.SafeAlpmHandle; - public IntPtr GetItems() => alpm.alpm_db_get_servers(_handle); - public int SetItems(IntPtr list) => alpm.alpm_db_set_servers(_handle, list); - public int AddItem(string item) => alpm.alpm_db_add_server(_handle, item); - public int RemoveItem(string item) => alpm.alpm_db_remove_server(_handle, item); - public IntPtr FindItem(string item) => alpm.alpm_list_find_str(GetItems(), item); + public SafeDatabaseHandle Handle { get; } + public IntPtr GetItems() => alpm.alpm_db_get_servers(Handle); public string PtrToItem(IntPtr p) => Marshal.PtrToStringUTF8(p)!; } - public ICollection Servers + public void AddServer(string url) => API.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)); + + public IEnumerable Servers { - get => new CollectionWrapper(new ServersAccessor(_handle)); + get => new EnumerableWrapper(new ServersAccessor(_handle)); set { foreach (var s in value) @@ -40,7 +51,6 @@ namespace Foodsoft.Alpm } } - public string Name => alpm.alpm_db_get_name(_handle); public SigLevel SigLevel => alpm.alpm_db_get_siglevel(_handle); @@ -48,7 +58,7 @@ namespace Foodsoft.Alpm public ErrNo Valid => alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : ErrNo.ERR_OK; - public bool Update(bool force) + public bool Update(bool force = false) { var err = alpm.alpm_db_update(force ? 1 : 0, _handle); if (err < 0) @@ -69,21 +79,18 @@ namespace Foodsoft.Alpm return null; throw new Exception(err); } + return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this); } - - private readonly struct PkgCacheAccessor : IReadOnlyItemsAccessor - { - private readonly SafeDatabaseHandle _handle; - public SafeAlpmHandle SafeAlpmHandle => _handle.SafeAlpmHandle; - public IntPtr GetItems() - { - throw new NotImplementedException(); - } - public Package PtrToItem(IntPtr p) + public PackageList PackageCache + { + get { - throw new NotImplementedException(); + var listPtr = alpm.alpm_db_get_pkgcache(_handle); + if (listPtr == IntPtr.Zero) + throw new Exception(alpm.alpm_errno(_handle.SafeAlpmHandle)); + return new PackageList(new SafeListHandle(listPtr, _handle), this); } } diff --git a/Depend.cs b/Alpm/Depend.cs similarity index 100% rename from Depend.cs rename to Alpm/Depend.cs diff --git a/Alpm/EnumerableWrapper`3.cs b/Alpm/EnumerableWrapper`3.cs new file mode 100644 index 0000000..3bdaed0 --- /dev/null +++ b/Alpm/EnumerableWrapper`3.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Foodsoft.Alpm +{ + internal struct EnumerableWrapper : IEnumerable where TImpl : struct, + IItemsReader + where THandle : SafeHandle + { + private TImpl _impl; + + public EnumerableWrapper(TImpl impl) + { + _impl = impl; + } + + public IEnumerator GetEnumerator() + { + var handle = _impl.Handle; + var release = false; + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + handle.DangerousAddRef(ref release); + if (!release) throw new ObjectDisposedException(_impl.GetType().FullName); + for (var list = _impl.GetItems(); list != IntPtr.Zero; list = Wrapper.ListNext(list)) + { + yield return _impl.PtrToItem(Wrapper.ListData(list)); + } + } + finally + { + if (release) + handle.DangerousRelease(); + } + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/ErrNo.cs b/Alpm/ErrNo.cs similarity index 100% rename from ErrNo.cs rename to Alpm/ErrNo.cs diff --git a/Exception.cs b/Alpm/Exception.cs similarity index 100% rename from Exception.cs rename to Alpm/Exception.cs diff --git a/File.cs b/Alpm/File.cs similarity index 100% rename from File.cs rename to Alpm/File.cs diff --git a/FileList.cs b/Alpm/FileList.cs similarity index 100% rename from FileList.cs rename to Alpm/FileList.cs diff --git a/Handle.cs b/Alpm/Handle.cs similarity index 100% rename from Handle.cs rename to Alpm/Handle.cs diff --git a/IAlpmItemsAccessor`1.cs b/Alpm/IAlpmItemsAccessor`1.cs similarity index 100% rename from IAlpmItemsAccessor`1.cs rename to Alpm/IAlpmItemsAccessor`1.cs diff --git a/Alpm/IItemsReader`2.cs b/Alpm/IItemsReader`2.cs new file mode 100644 index 0000000..0d442d7 --- /dev/null +++ b/Alpm/IItemsReader`2.cs @@ -0,0 +1,12 @@ +using System; +using System.Runtime.InteropServices; + +namespace Foodsoft.Alpm +{ + internal interface IItemsReader where THandle : SafeHandle + { + public THandle Handle { get; } + public IntPtr GetItems(); + public TElement PtrToItem(IntPtr p); + } +} \ No newline at end of file diff --git a/IPackageData.cs b/Alpm/IPackageData.cs similarity index 95% rename from IPackageData.cs rename to Alpm/IPackageData.cs index 9c4f62c..82f204c 100644 --- a/IPackageData.cs +++ b/Alpm/IPackageData.cs @@ -26,7 +26,7 @@ namespace Foodsoft.Alpm Signature = (1 << 3) } - public interface IPackageData + public interface IPackageData : IDisposable { public string Filename { get; } public string Base { get; } @@ -44,7 +44,7 @@ namespace Foodsoft.Alpm public long Size { get; } public long InstalledSize { get; } public InstallReason InstallReason { get; } - public IReadOnlyCollection Licenses { get; } + public IEnumerable Licenses { get; } public IReadOnlyCollection Groups { get; } public IReadOnlyCollection Depends { get; } public IReadOnlyCollection OptDepends { get; } diff --git a/Junk.cs b/Alpm/Junk.cs similarity index 100% rename from Junk.cs rename to Alpm/Junk.cs diff --git a/Package.cs b/Alpm/Package.cs similarity index 92% rename from Package.cs rename to Alpm/Package.cs index 00e208d..54132e1 100644 --- a/Package.cs +++ b/Alpm/Package.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace Foodsoft.Alpm { - public class Package : IPackageData + public abstract class Package : IPackageData { internal SafePackageHandle Handle { get; } @@ -30,7 +31,7 @@ namespace Foodsoft.Alpm public long InstalledSize => alpm.alpm_pkg_get_isize(Handle); public InstallReason InstallReason => alpm.alpm_pkg_get_reason(Handle); - public IReadOnlyCollection Licenses { get; } + public IEnumerable Licenses { get; } public IReadOnlyCollection Groups { get; } public IReadOnlyCollection Depends { get; } public IReadOnlyCollection OptDepends { get; } @@ -61,8 +62,12 @@ namespace Foodsoft.Alpm { throw new NotImplementedException(); } - - + + + public void Dispose() + { + Handle.Dispose(); + } } } \ No newline at end of file diff --git a/Alpm/PackageList.cs b/Alpm/PackageList.cs new file mode 100644 index 0000000..1bf86e5 --- /dev/null +++ b/Alpm/PackageList.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Foodsoft.Alpm +{ + public struct PackageList : IEnumerable, IDisposable + { + private SafeListHandle _handle; + private Database _db; + + internal PackageList(SafeListHandle handle, Database db) + { + _handle = handle; + _db = db; + } + + public IEnumerator GetEnumerator() + { + var release = false; + + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + _handle.DangerousAddRef(ref release); + if (!release) throw new ObjectDisposedException(_handle.GetType().FullName); + for (var list = _handle.DangerousGetHandle(); list != IntPtr.Zero; list = Wrapper.ListNext(list)) + { + yield return new CachePackage( + new SafeCachePackageHandle(Wrapper.ListData(list), _handle.ParentHandle), _db); + } + } + finally + { + if (release) + _handle.DangerousRelease(); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Dispose() + { + _handle.Dispose(); + } + } +} \ No newline at end of file diff --git a/SafeAlpmHandle.cs b/Alpm/SafeAlpmHandle.cs similarity index 100% rename from SafeAlpmHandle.cs rename to Alpm/SafeAlpmHandle.cs diff --git a/SafeCachePackageHandle.cs b/Alpm/SafeCachePackageHandle.cs similarity index 73% rename from SafeCachePackageHandle.cs rename to Alpm/SafeCachePackageHandle.cs index c47a030..1b70949 100644 --- a/SafeCachePackageHandle.cs +++ b/Alpm/SafeCachePackageHandle.cs @@ -6,21 +6,16 @@ namespace Foodsoft.Alpm { internal sealed class SafeCachePackageHandle : SafePackageHandle { - internal SafeDatabaseHandle SafeDatabaseHandle - { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - [PrePrepareMethod] - get; - } = null!; - internal SafeAlpmHandle SafeAlpmHandle => SafeDatabaseHandle.SafeAlpmHandle; + internal SafeDatabaseHandle SafeDatabaseHandle { get; } = null!; [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [PrePrepareMethod] - internal SafeCachePackageHandle(IntPtr pkgPtr, SafeDatabaseHandle dbHandle) + internal SafeCachePackageHandle(IntPtr ptr, SafeDatabaseHandle dbHandle) : base() { var success = false; + RuntimeHelpers.PrepareConstrainedRegions(); try { } finally @@ -28,15 +23,14 @@ namespace Foodsoft.Alpm dbHandle.DangerousAddRef(ref success); if (success) { - handle = pkgPtr; SafeDatabaseHandle = dbHandle; + handle = ptr; } } if (!success) throw new ObjectDisposedException(GetType().FullName); } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod] protected override bool ReleaseHandle() { SafeDatabaseHandle.DangerousRelease(); diff --git a/SafeDatabaseHandle.cs b/Alpm/SafeDatabaseHandle.cs similarity index 94% rename from SafeDatabaseHandle.cs rename to Alpm/SafeDatabaseHandle.cs index a1b249a..3144625 100644 --- a/SafeDatabaseHandle.cs +++ b/Alpm/SafeDatabaseHandle.cs @@ -39,9 +39,8 @@ namespace Foodsoft.Alpm [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod] protected override bool ReleaseHandle() { - var ret = alpm.alpm_db_unregister(handle) == 0; SafeAlpmHandle.DangerousRelease(); - return ret; + return true; } public override bool IsInvalid diff --git a/SafeListHandle.cs b/Alpm/SafeListHandle`1.cs similarity index 70% rename from SafeListHandle.cs rename to Alpm/SafeListHandle`1.cs index 911f1c5..996f971 100644 --- a/SafeListHandle.cs +++ b/Alpm/SafeListHandle`1.cs @@ -5,18 +5,18 @@ using System.Runtime.InteropServices; namespace Foodsoft.Alpm { - internal sealed class SafeListHandle : SafeHandle + internal sealed class SafeListHandle : SafeHandle where TParent: SafeHandle { - public SafeAlpmHandle SafeAlpmHandle + internal TParent ParentHandle { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [PrePrepareMethod] get; } = null!; - + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] [PrePrepareMethod] - internal SafeListHandle(SafeAlpmHandle safeAlpmHandle) + internal SafeListHandle(IntPtr listPtr, TParent parentHandle) : base(IntPtr.Zero, true) { var success = false; @@ -24,11 +24,14 @@ namespace Foodsoft.Alpm try { } finally { - safeAlpmHandle.DangerousAddRef(ref success); + parentHandle.DangerousAddRef(ref success); if (success) - SafeAlpmHandle = safeAlpmHandle; - } + { + ParentHandle = parentHandle; + handle = listPtr; + } + } if (!success) throw new ObjectDisposedException(GetType().FullName); } @@ -36,14 +39,14 @@ namespace Foodsoft.Alpm [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod] protected override bool ReleaseHandle() { - SafeAlpmHandle.DangerousRelease(); + ParentHandle.DangerousRelease(); return true; } public override bool IsInvalid { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod] - get => SafeAlpmHandle.IsInvalid; + get => ParentHandle.IsInvalid; } } } \ No newline at end of file diff --git a/SafePackageHandle.cs b/Alpm/SafePackageHandle.cs similarity index 100% rename from SafePackageHandle.cs rename to Alpm/SafePackageHandle.cs diff --git a/UTF8InMarshaler.cs b/Alpm/UTF8InMarshaler.cs similarity index 99% rename from UTF8InMarshaler.cs rename to Alpm/UTF8InMarshaler.cs index 48dc3e0..e51df4e 100644 --- a/UTF8InMarshaler.cs +++ b/Alpm/UTF8InMarshaler.cs @@ -8,7 +8,6 @@ namespace Foodsoft.Alpm { private static readonly UTF8InMarshaler _instance = default; - public void CleanUpManagedData(object managedObj) { } public void CleanUpNativeData(IntPtr pNativeData) diff --git a/UTF8OutMarshaler.cs b/Alpm/UTF8OutMarshaler.cs similarity index 100% rename from UTF8OutMarshaler.cs rename to Alpm/UTF8OutMarshaler.cs diff --git a/Alpm/Wrapper.cs b/Alpm/Wrapper.cs new file mode 100644 index 0000000..bb06c11 --- /dev/null +++ b/Alpm/Wrapper.cs @@ -0,0 +1,10 @@ +using System; + +namespace Foodsoft.Alpm +{ + internal static class Wrapper + { + internal static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next; + internal static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data; + } +} \ No newline at end of file diff --git a/alpm.cs b/Alpm/alpm.cs similarity index 98% rename from alpm.cs rename to Alpm/alpm.cs index 30f61ed..7cb4d0d 100644 --- a/alpm.cs +++ b/Alpm/alpm.cs @@ -187,7 +187,7 @@ namespace Foodsoft.Alpm string url); [DllImport(nameof(alpm))] - public static extern int alpm_db_unregister(IntPtr db); + public static extern int alpm_db_unregister(SafeDatabaseHandle db); [DllImport(nameof(alpm))] [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8OutMarshaler))] @@ -219,7 +219,7 @@ namespace Foodsoft.Alpm string name); [DllImport(nameof(alpm))] - public static extern IntPtr alpm_pkg_get_pkgcache(SafeDatabaseHandle db); + public static extern IntPtr alpm_db_get_pkgcache(SafeDatabaseHandle db); } } \ No newline at end of file diff --git a/AlpmOld.cs b/AlpmOld.cs deleted file mode 100644 index 61122ce..0000000 --- a/AlpmOld.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; - -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable UnassignedReadonlyField -// ReSharper disable UnusedMember.Global - -// ReSharper disable InconsistentNaming - -namespace Foodsoft.Alpm -{ - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct alpm_pkg_p - { - private IntPtr ptr; - } - -} \ No newline at end of file diff --git a/DotNetAlpm.sln b/DotNetAlpm.sln new file mode 100644 index 0000000..62cb70e --- /dev/null +++ b/DotNetAlpm.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Alpm", "Alpm\Alpm.csproj", "{6AEC7D1A-DA7C-44CB-A339-7CBE5FCB88B1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples", "Samples\Samples.csproj", "{1215BE9E-B4F4-4F42-B4A2-E890C5EAA903}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6AEC7D1A-DA7C-44CB-A339-7CBE5FCB88B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6AEC7D1A-DA7C-44CB-A339-7CBE5FCB88B1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6AEC7D1A-DA7C-44CB-A339-7CBE5FCB88B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6AEC7D1A-DA7C-44CB-A339-7CBE5FCB88B1}.Release|Any CPU.Build.0 = Release|Any CPU + {1215BE9E-B4F4-4F42-B4A2-E890C5EAA903}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1215BE9E-B4F4-4F42-B4A2-E890C5EAA903}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1215BE9E-B4F4-4F42-B4A2-E890C5EAA903}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1215BE9E-B4F4-4F42-B4A2-E890C5EAA903}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/DotNetAlpm.sln.DotSettings b/DotNetAlpm.sln.DotSettings new file mode 100644 index 0000000..58ae2f7 --- /dev/null +++ b/DotNetAlpm.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Folder.DotSettings b/Folder.DotSettings deleted file mode 100644 index 1c8e73a..0000000 --- a/Folder.DotSettings +++ /dev/null @@ -1,12 +0,0 @@ - - True - True - True - True - True - True - True - True - True - True - True \ No newline at end of file diff --git a/IReadOnlyItemsAccessor`1.cs b/IReadOnlyItemsAccessor`1.cs deleted file mode 100644 index 38744e3..0000000 --- a/IReadOnlyItemsAccessor`1.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Foodsoft.Alpm -{ - internal interface IReadOnlyItemsAccessor - { - SafeAlpmHandle SafeAlpmHandle { get; } - public IntPtr GetItems(); - public TElement PtrToItem(IntPtr p); - } -} \ No newline at end of file diff --git a/Program.cs b/Program.cs deleted file mode 100644 index 63e596f..0000000 --- a/Program.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using Foodsoft.Alpm; - -namespace Foodsoft.Alpm -{ - class Program - { - static void Main(string[] args) - { - ErrNo err = ErrNo.ERR_OK; - - using var h = new Handle("/", "/home/luebsj/db"); - using var db = h.RegisterSyncDB("jkl-repo", SigLevel.SIG_PACKAGE_OPTIONAL | SigLevel.SIG_USE_DEFAULT); - - db.Servers = new List {"http://a.b.c", "http://d.e.f", "http://arch.johnluebs.com/x86_64"}; - foreach (var a in db.Servers) - { - Console.WriteLine("Hello {0}", a); - } - var b = new string[3]; - db.Servers.CopyTo(b, 0); - Console.WriteLine("Hello World! {0} {1} {2}", db.Name, API.Version, - b[0]); - } - } -} diff --git a/ReadOnlyCollectionWrapper`2.cs b/ReadOnlyCollectionWrapper`2.cs deleted file mode 100644 index 1d08dde..0000000 --- a/ReadOnlyCollectionWrapper`2.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace Foodsoft.Alpm -{ - internal class ReadOnlyCollectionWrapper : IReadOnlyCollection where TImpl : struct, - IReadOnlyItemsAccessor - { - private TImpl _impl; - private SafeAlpmHandle SafeAlpmHandle => _impl.SafeAlpmHandle; - - public ReadOnlyCollectionWrapper(TImpl impl) - { - _impl = impl; - } - - private static unsafe IntPtr ListNext(IntPtr list) => ((alpm_list_t*) list)->next; - private static unsafe IntPtr ListData(IntPtr list) => ((alpm_list_t*) list)->data; - public IEnumerator GetEnumerator() - { - var safeAlpmHandle = _impl.SafeAlpmHandle; - var release = false; - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { - safeAlpmHandle.DangerousAddRef(ref release); - if (!release) throw new ObjectDisposedException(_impl.GetType().FullName); - for (var list = _impl.GetItems(); list != IntPtr.Zero; list = ListNext(list)) - { - yield return _impl.PtrToItem(ListData(list)); - } - } - finally - { - if (release) - safeAlpmHandle.DangerousRelease(); - } - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public int Count => (int) alpm.alpm_list_count(_impl.GetItems()); - } -} \ No newline at end of file diff --git a/Samples/Program.cs b/Samples/Program.cs new file mode 100644 index 0000000..4d5ca61 --- /dev/null +++ b/Samples/Program.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Immutable; +using Foodsoft.Alpm; + +namespace Samples +{ + class Program + { + static void Other() + { + using var h = new Handle("/", "/home/luebsj/db"); + using var db = h.RegisterSyncDB("jkl-repo", SigLevel.SIG_PACKAGE_OPTIONAL | SigLevel.SIG_USE_DEFAULT); + + db.AddServer("http://arch.johnluebs.com/x86_64"); + db.Update(false); + foreach (var a in db.Servers) + { + Console.WriteLine("Hello {0}", a); + } + + var servers = db.Servers; + var b = new string[3]; + var l = db.Servers.ToImmutableList(); + + using var cache = db.PackageCache; + foreach ( var p in cache) using(p) + { + Console.WriteLine("Hello: {0} {1} {2}", p.Name, p.Filename, p.BuildDate); + } + + Console.WriteLine("Hello World! {0} {1} {2}", db.Name, API.Version, + l[0]); + } + static void Main(string[] args) + { + Other(); + } + } +} diff --git a/Samples/Samples.csproj b/Samples/Samples.csproj new file mode 100644 index 0000000..5864e5b --- /dev/null +++ b/Samples/Samples.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/Wrapper.cs b/Wrapper.cs deleted file mode 100644 index 30607ee..0000000 --- a/Wrapper.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System; - -namespace Foodsoft.Alpm -{ - public class Wrapper - { } -} \ No newline at end of file