checkpoint

This commit is contained in:
2020-04-30 20:40:52 -04:00
parent 9aa367e9f5
commit abba062f4f
28 changed files with 615 additions and 544 deletions

View File

@@ -1,5 +1,3 @@
using System;
namespace Foodsoft.Alpm
{
public static class API

View File

@@ -1,16 +1,15 @@
using System;
using System.Runtime.Serialization;
using Foodsoft.Alpm;
namespace Foodsoft.Alpm
{
[Serializable()]
public class AlpmException : System.Exception
[Serializable]
public class AlpmException : Exception
{
public AlpmException() { }
internal AlpmException(SafeAlpmHandle handle) : base(alpm.alpm_strerror(alpm.alpm_errno(handle))) { }
public AlpmException(ErrNo errno) : base(alpm.alpm_strerror(errno)) { }
public AlpmException(ErrNo errno, System.Exception inner) : base(alpm.alpm_strerror(errno), inner) { }
public AlpmException(Error errno) : base(alpm.alpm_strerror(errno)) { }
public AlpmException(Error errno, Exception inner) : base(alpm.alpm_strerror(errno), inner) { }
protected AlpmException(SerializationInfo info,
StreamingContext context) : base(info, context) { }

View File

@@ -8,9 +8,20 @@ namespace Foodsoft.Alpm
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);
public bool Equals(Backup other)
{
return Name == other.Name && Hash == other.Hash;
}
public override bool Equals(object? obj)
{
return obj is Backup other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Hash);
}
[StructLayout(LayoutKind.Sequential)]
private readonly unsafe struct NativeBackup

View File

@@ -10,6 +10,14 @@ namespace Foodsoft.Alpm
public override Database? DB { get; }
public bool CheckMD5Sum()
{
var ret = alpm.alpm_pkg_checkmd5sum(Handle);
if (ret == 0) return true;
var errno = alpm.alpm_errno(Handle.SafeAlpmHandle);
return errno == Error.PkgInvalid ? false : throw new AlpmException(errno);
}
public void SetInstallReason(InstallReason reason)
{
if (alpm.alpm_pkg_set_reason(Handle, reason) != 0)

View File

@@ -1,20 +1,16 @@
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;
private readonly IntPtr _listPtr;
private readonly Database _db;
private readonly IntPtr _listPtr;
private readonly SafeDatabaseHandle _parentHandle;
internal CachePackageList(IntPtr listPtr, SafeDatabaseHandle parentHandle, Database db)
{
@@ -23,45 +19,15 @@ namespace Foodsoft.Alpm
_db = db;
}
[PrePrepareMethod]
public IEnumerator<CachePackage> GetEnumerator()
{
var release = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
_parentHandle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_parentHandle.GetType().FullName);
for (var list = _listPtr; list != IntPtr.Zero; list = Detail.ListNext(list))
{
yield return new CachePackage(
new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db);
}
}
finally
{
if (release)
_parentHandle.DangerousRelease();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public bool Contains(CachePackage item)
{
var name = item.Name;
return _parentHandle.UseHandle(_listPtr, (list) =>
return _parentHandle.UseHandle(_listPtr, list =>
{
for (; list != IntPtr.Zero; list = Detail.ListNext(list))
{
if (name == alpm.alpm_pkg_get_name(list))
return true;
}
return false;
});
@@ -69,29 +35,16 @@ namespace Foodsoft.Alpm
public void CopyTo(CachePackage[] array, int arrayIndex)
{
_parentHandle.UseHandle(_listPtr, (list) =>
_parentHandle.UseHandle(_listPtr, list =>
{
for (; list != IntPtr.Zero; list = Detail.ListNext(list))
{
array[arrayIndex++] = new CachePackage(
new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db);
}
return 0;
});
}
public CachePackage? FindSatisfier(string depString)
{
return _parentHandle.UseHandle(_listPtr, (list) =>
{
var pkgPtr = alpm.alpm_find_satisfier(list, depString);
return pkgPtr != IntPtr.Zero
? new CachePackage(new SafeCachePackageHandle(pkgPtr, _parentHandle), _db)
: null;
});
}
public void Add(CachePackage item)
{
throw new NotSupportedException();
@@ -107,8 +60,49 @@ namespace Foodsoft.Alpm
throw new NotSupportedException();
}
public int Count => _parentHandle.UseHandle(_listPtr, (list) => (int) alpm.alpm_list_count(list));
public int Count => _listPtr == IntPtr.Zero
? 0
: _parentHandle.UseHandle(_listPtr, list => (int) alpm.alpm_list_count(list));
public bool IsReadOnly => true;
[PrePrepareMethod]
public IEnumerator<CachePackage> GetEnumerator()
{
if (_listPtr == IntPtr.Zero)
yield break;
var release = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
_parentHandle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_parentHandle.GetType().FullName);
for (var list = _listPtr; list != IntPtr.Zero; list = Detail.ListNext(list))
yield return new CachePackage(
new SafeCachePackageHandle(Detail.ListData(list), _parentHandle), _db);
}
finally
{
if (release)
_parentHandle.DangerousRelease();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public CachePackage? FindSatisfier(string depString)
{
return _parentHandle.UseHandle(_listPtr, list =>
{
var pkgPtr = alpm.alpm_find_satisfier(list, depString);
return pkgPtr != IntPtr.Zero
? new CachePackage(new SafeCachePackageHandle(pkgPtr, _parentHandle), _db)
: null;
});
}
}
}

View File

@@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
namespace Foodsoft.Alpm
{
@@ -11,26 +12,22 @@ namespace Foodsoft.Alpm
public enum UsageFlags
{
Sync = 1,
Search = (1 << 1),
Install = (1 << 2),
Upgrade = (1 << 3),
All = (1 << 4) - 1,
Search = 1 << 1,
Install = 1 << 2,
Upgrade = 1 << 3,
All = (1 << 4) - 1
}
private readonly SafeDatabaseHandle _handle;
internal Database(SafeDatabaseHandle handle) => _handle = handle;
public void Unregister() => _handle.Close();
public void AddServer(string url) =>
Detail.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url));
public bool RemoveServer(string url) =>
Detail.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url));
internal Database(SafeDatabaseHandle handle)
{
_handle = handle;
}
// FIXME: This is "bug correct", but probably dumb to do it this way, instead just call add_server
// like all the stuff in handle.
// Also this stupid thing leaks the duped strings on failure.
public IEnumerable<string> Servers
{
get => EnumerableWrapper.Create(_handle, alpm.alpm_db_get_servers);
@@ -44,10 +41,9 @@ namespace Foodsoft.Alpm
{
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var s in value)
{
if (alpm.alpm_list_append_strdup(ref listPtr, s) == IntPtr.Zero)
throw new AlpmException(ErrNo.ERR_MEMORY);
}
throw new AlpmException(Error.Memory);
success = true;
}
finally
@@ -67,33 +63,8 @@ namespace Foodsoft.Alpm
public SigLevel SigLevel => alpm.alpm_db_get_siglevel(_handle);
public ErrNo Valid =>
alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : ErrNo.ERR_OK;
public bool Update(bool force = false)
{
var err = alpm.alpm_db_update(force ? 1 : 0, _handle);
if (err < 0)
{
throw new AlpmException(_handle.SafeAlpmHandle);
}
return err == 0;
}
public Package? GetPackage(string name)
{
var pkgPtr = alpm.alpm_pkg_get_pkg(_handle, name);
if (pkgPtr == IntPtr.Zero)
{
var err = alpm.alpm_errno(_handle.SafeAlpmHandle);
if (err == ErrNo.ERR_PKG_NOT_FOUND)
return null;
throw new AlpmException(err);
}
return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this);
}
public Error Valid =>
alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : Error.OK;
public CachePackageList PackageCache
{
@@ -106,16 +77,68 @@ namespace Foodsoft.Alpm
}
}
public CachePackageList Search()
public UsageFlags Usage
{
get => Detail.WrapErrorOut<SafeDatabaseHandle, UsageFlags>(_handle.SafeAlpmHandle, _handle,
alpm.alpm_db_get_usage);
set => Detail.WrapErrorIn(_handle.SafeAlpmHandle, _handle, value, alpm.alpm_db_set_usage);
}
public UsageFlags Usage => Detail.WrapError<UsageFlags, SafeDatabaseHandle>(_handle.SafeAlpmHandle, _handle, alpm.alpm_db_get_usage);
public void Dispose()
{
_handle.Dispose();
}
public void Unregister()
{
_handle.Close();
}
public void AddServer(string url)
{
Detail.WrapError(_handle.SafeAlpmHandle, () => alpm.alpm_db_add_server(_handle, url));
}
public bool RemoveServer(string url)
{
return Detail.WrapErrorBool(_handle.SafeAlpmHandle, () => alpm.alpm_db_remove_server(_handle, url));
}
public bool Update(bool force = false)
{
var err = alpm.alpm_db_update(force ? 1 : 0, _handle);
if (err < 0) throw new AlpmException(_handle.SafeAlpmHandle);
return err == 0;
}
public Package? GetPackage(string name)
{
var pkgPtr = alpm.alpm_pkg_get_pkg(_handle, name);
if (pkgPtr == IntPtr.Zero)
{
var err = alpm.alpm_errno(_handle.SafeAlpmHandle);
if (err == Error.PkgNotFound)
return null;
throw new AlpmException(err);
}
return new CachePackage(new SafeCachePackageHandle(pkgPtr, _handle), this);
}
[PrePrepareMethod]
[SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")]
public CachePackageList Search(IEnumerable<string> needles)
{
var result = Detail.UseStringList(needles, listPtr => alpm.alpm_db_search(_handle, listPtr));
if (result == IntPtr.Zero)
{
var errNo = alpm.alpm_errno(_handle.SafeAlpmHandle);
if (errNo != Error.OK)
throw new AlpmException(errNo);
}
return new CachePackageList(result, _handle, this);
}
}
}

View File

@@ -1,6 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
@@ -16,30 +14,7 @@ namespace Foodsoft.Alpm
GreaterThan,
LessThan
}
public string Name { get; }
public string Version { get; }
public string Description { get; }
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
{
internal readonly sbyte* name;
internal readonly sbyte* version;
internal readonly sbyte* description;
internal readonly ulong name_hash;
internal readonly Depend.ModType mod;
}
internal unsafe Depend(IntPtr ptr)
{
var native = (NativeDepend*) ptr;
@@ -49,5 +24,37 @@ namespace Foodsoft.Alpm
NameHash = native->name_hash;
Mod = native->mod;
}
public string Name { get; }
public string Version { get; }
public string Description { get; }
public ulong NameHash { get; }
public ModType Mod { get; }
public bool Equals(Depend? other)
{
return !ReferenceEquals(other, null) && ReferenceEquals(this, other) &&
Name == other.Name && Version == other.Version && Mod == other.Mod;
}
public override bool Equals(object? obj)
{
return obj is Depend other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Version, (int) Mod);
}
[StructLayout(LayoutKind.Sequential)]
private readonly unsafe struct NativeDepend
{
internal readonly sbyte* name;
internal readonly sbyte* version;
internal readonly sbyte* description;
internal readonly ulong name_hash;
internal readonly ModType mod;
}
}
}

View File

@@ -1,14 +1,26 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace Foodsoft.Alpm
{
[SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")]
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;
internal static unsafe IntPtr ListNext(IntPtr list)
{
return ((alpm_list_t*) list)->next;
}
internal static unsafe IntPtr ListData(IntPtr list)
{
return ((alpm_list_t*) list)->data;
}
internal static TResult UseHandle<TResult>(this SafeHandle handle, IntPtr ptr, Func<IntPtr, TResult> op)
{
@@ -28,16 +40,61 @@ namespace Foodsoft.Alpm
}
}
internal static TResult UseHandle<TResult>(this SafeHandle handle, Func<IntPtr, TResult> op) =>
handle.UseHandle(handle.DangerousGetHandle(), op);
internal static void SetStringCollection(IEnumerable<string> value, SafeAlpmHandle safeAlpmHandle, Func<string, int> op)
internal static TResult UseHandle<TResult>(this SafeHandle handle, Func<IntPtr, TResult> op)
{
return handle.UseHandle(handle.DangerousGetHandle(), op);
}
internal static void SetStringCollection(IEnumerable<string> value, SafeAlpmHandle safeAlpmHandle,
Func<string, int> op)
{
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var s in value)
{
if (op(s) < 0)
throw new AlpmException(safeAlpmHandle);
}
internal static unsafe TResult UseStringList<TResult>(IEnumerable<string> strings, Func<IntPtr, TResult> op)
{
var listPtr = IntPtr.Zero;
var strArray = strings as string[] ?? strings.ToArray();
var numBytes = 0;
foreach (var s in strArray) numBytes += Encoding.UTF8.GetMaxByteCount(s.Length) + 1;
var pool = ArrayPool<byte>.Shared;
byte[] poolBuffer = pool.Rent(numBytes);
try
{
fixed (byte* pBuf = poolBuffer)
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
var start = 0;
foreach (var s in strArray)
fixed (char* pSrc = s)
{
var pDest = &pBuf[start];
var nbWritten =
Encoding.UTF8.GetBytes(pSrc, s.Length, pDest, poolBuffer.Length - start);
pDest[nbWritten] = 0;
if (alpm.alpm_list_append(ref listPtr, (IntPtr) pDest) == IntPtr.Zero)
throw new AlpmException(Error.Memory);
start += nbWritten + 1;
}
return op(listPtr);
}
finally
{
alpm.alpm_list_free(listPtr);
}
}
}
finally
{
pool.Return(poolBuffer);
}
}
@@ -48,9 +105,7 @@ namespace Foodsoft.Alpm
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)
internal static T WrapErrorOut<THandle, T>(SafeAlpmHandle alpmHandle, THandle handle, OutFunc<THandle, T> f)
{
var err = f(handle, out var result);
if (err != 0)
@@ -58,14 +113,22 @@ namespace Foodsoft.Alpm
return result;
}
internal static void WrapErrorIn<THandle, T>(SafeAlpmHandle alpmHandle, THandle handle, T value,
Func<THandle, T, int> f)
{
var err = f(handle, value);
if (err != 0)
throw new AlpmException(alpmHandle);
}
internal static bool WrapErrorBool(SafeAlpmHandle h, Func<int> f)
{
var err = f();
if (err < 0)
{
throw new AlpmException(h);
}
if (err < 0) throw new AlpmException(h);
return err == 0;
}
internal delegate int OutFunc<in THandle, T>(THandle handle, out T result);
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -14,17 +13,17 @@ namespace Foodsoft.Alpm
{
return new EnumerableWrapper<string, THandle>(handle, getItems, Marshal.PtrToStringUTF8!);
}
internal static EnumerableWrapper<Depend, THandle> CreateForDepend<THandle>(THandle handle,
Func<THandle, IntPtr> getItems) where THandle : SafeHandle
{
return new EnumerableWrapper<Depend, THandle>(handle, getItems, (ptr) => new Depend(ptr));
return new EnumerableWrapper<Depend, THandle>(handle, getItems, ptr => new Depend(ptr));
}
internal static EnumerableWrapper<Backup, THandle> CreateForBackup<THandle>(THandle handle,
Func<THandle, IntPtr> getItems) where THandle : SafeHandle
{
return new EnumerableWrapper<Backup, THandle>(handle, getItems, (ptr) => new Backup(ptr));
return new EnumerableWrapper<Backup, THandle>(handle, getItems, ptr => new Backup(ptr));
}
}
@@ -41,6 +40,8 @@ namespace Foodsoft.Alpm
_getElement = getElement;
}
public bool IsReadOnly => true;
public IEnumerator<TElement> GetEnumerator()
{
var release = false;
@@ -51,9 +52,7 @@ namespace Foodsoft.Alpm
_handle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_handle.GetType().FullName);
for (var list = _getItems(_handle); list != IntPtr.Zero; list = Detail.ListNext(list))
{
yield return _getElement(Detail.ListData(list));
}
}
finally
{
@@ -62,7 +61,10 @@ namespace Foodsoft.Alpm
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Count
{
@@ -70,7 +72,7 @@ namespace Foodsoft.Alpm
{
var getItems = _getItems;
var handle = _handle;
return handle.UseHandle((_) => (int) alpm.alpm_list_count(getItems(handle)));
return handle.UseHandle(_ => (int) alpm.alpm_list_count(getItems(handle)));
}
}
@@ -82,16 +84,14 @@ namespace Foodsoft.Alpm
switch (item)
{
case string s:
return handle.UseHandle((_) => alpm.alpm_list_find_str(getItems(handle), s) != (IntPtr.Zero));
return handle.UseHandle(_ => alpm.alpm_list_find_str(getItems(handle), s) != IntPtr.Zero);
default:
var comparer = EqualityComparer<TElement>.Default;
return handle.UseHandle((_) =>
return handle.UseHandle(_ =>
{
for (var list = getItems(handle); list != IntPtr.Zero; list = Detail.ListNext(list))
{
if (comparer.Equals(item, getElement(Detail.ListData(list))))
return true;
}
return false;
});
@@ -103,12 +103,10 @@ namespace Foodsoft.Alpm
var getItems = _getItems;
var getElement = _getElement;
var handle = _handle;
handle.UseHandle((_) =>
handle.UseHandle(_ =>
{
for (var list = getItems(handle); list != IntPtr.Zero; list = Detail.ListNext(list))
{
array[arrayIndex++] = getElement(Detail.ListData(list));
}
return arrayIndex;
});
@@ -128,7 +126,5 @@ namespace Foodsoft.Alpm
{
throw new NotSupportedException();
}
public bool IsReadOnly => true;
}
}

View File

@@ -2,6 +2,85 @@ using System;
namespace Foodsoft.Alpm
{
public enum Error
{
OK = 0,
Memory,
System,
Badperms,
NotAFile,
NotADir,
WrongArgs,
DiskSpace,
/* Interface */
HandleNull,
HandleNotNull,
HandleLock,
/* Databases */
DBOpen,
DBCreate,
DBNull,
DBNotNull,
DBNotFound,
DBInvalid,
DBInvalidSig,
DBVersion,
DBWrite,
DBRemove,
/* Servers */
ServerBadUrl,
ServerNone,
/* Transactions */
TransNotNull,
TransNull,
TransDupTarget,
TransNotInitialized,
TransNotPrepared,
TransAbort,
TransType,
TransNotLocked,
TransHookFailed,
/* Packages */
PkgNotFound,
PkgIgnored,
PkgInvalid,
PkgInvalidChecksum,
PkgInvalidSig,
PkgMissingSig,
PkgOpen,
PkgCantRemove,
PkgInvalidName,
PkgInvalidArch,
PkgRepoNotFound,
/* Signatures */
SigMissing,
SigInvalid,
/* Dependencies */
UnsatisfiedDeps,
ConflictingDeps,
FileConflicts,
/*Misc*/
Retrieve,
InvalidRegex,
/*ExternalLibraryors*/
Libarchive,
Libcurl,
ExternalDownload,
Gpgme,
/*MissingCompileTimeFeatures*/
MissingCapabilitySignatures
}
[Flags]
public enum LogLevel
{

View File

@@ -1,81 +0,0 @@
namespace Foodsoft.Alpm
{
public enum ErrNo
{
ERR_OK = 0,
ERR_MEMORY,
ERR_SYSTEM,
ERR_BADPERMS,
ERR_NOT_A_FILE,
ERR_NOT_A_DIR,
ERR_WRONG_ARGS,
ERR_DISK_SPACE,
/* Interface */
ERR_HANDLE_NULL,
ERR_HANDLE_NOT_NULL,
ERR_HANDLE_LOCK,
/* Databases */
ERR_DB_OPEN,
ERR_DB_CREATE,
ERR_DB_NULL,
ERR_DB_NOT_NULL,
ERR_DB_NOT_FOUND,
ERR_DB_INVALID,
ERR_DB_INVALID_SIG,
ERR_DB_VERSION,
ERR_DB_WRITE,
ERR_DB_REMOVE,
/* Servers */
ERR_SERVER_BAD_URL,
ERR_SERVER_NONE,
/* Transactions */
ERR_TRANS_NOT_NULL,
ERR_TRANS_NULL,
ERR_TRANS_DUP_TARGET,
ERR_TRANS_NOT_INITIALIZED,
ERR_TRANS_NOT_PREPARED,
ERR_TRANS_ABORT,
ERR_TRANS_TYPE,
ERR_TRANS_NOT_LOCKED,
ERR_TRANS_HOOK_FAILED,
/* Packages */
ERR_PKG_NOT_FOUND,
ERR_PKG_IGNORED,
ERR_PKG_INVALID,
ERR_PKG_INVALID_CHECKSUM,
ERR_PKG_INVALID_SIG,
ERR_PKG_MISSING_SIG,
ERR_PKG_OPEN,
ERR_PKG_CANT_REMOVE,
ERR_PKG_INVALID_NAME,
ERR_PKG_INVALID_ARCH,
ERR_PKG_REPO_NOT_FOUND,
/* Signatures */
ERR_SIG_MISSING,
ERR_SIG_INVALID,
/* Dependencies */
ERR_UNSATISFIED_DEPS,
ERR_CONFLICTING_DEPS,
ERR_FILE_CONFLICTS,
/* Misc */
ERR_RETRIEVE,
ERR_INVALID_REGEX,
/* External library errors */
ERR_LIBARCHIVE,
ERR_LIBCURL,
ERR_EXTERNAL_DOWNLOAD,
ERR_GPGME,
/* Missing compile-time features */
ERR_MISSING_CAPABILITY_SIGNATURES
}
}

View File

@@ -27,7 +27,8 @@ namespace Foodsoft.Alpm
if (!release) throw new ObjectDisposedException(handle.GetType().FullName);
refs[pkgPtr] = pkg;
listPtr = alpm.alpm_list_add(listPtr, handle.DangerousGetHandle());
if (alpm.alpm_list_append(ref listPtr, handle.DangerousGetHandle()) == IntPtr.Zero)
throw new AlpmException(Error.Memory);
}
var foundPtr = alpm.alpm_find_satisfier(listPtr, depString);

View File

@@ -1,7 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Foodsoft.Alpm.Marshalling;
namespace Foodsoft.Alpm
{
@@ -28,5 +26,4 @@ namespace Foodsoft.Alpm
Mode = native->mode;
}
}
}

View File

@@ -19,12 +19,13 @@ namespace Foodsoft.Alpm
public File? Contains(string path)
{
return _handle.UseHandle(_ptr, (ptr) =>
return _handle.UseHandle(_ptr, ptr =>
{
var foundPtr = alpm.alpm_filelist_contains(ptr, path);
return foundPtr != IntPtr.Zero ? new File(foundPtr) : (File?) null;
});
}
public IEnumerator<File> GetEnumerator()
{
var release = false;
@@ -35,10 +36,7 @@ namespace Foodsoft.Alpm
_handle.DangerousAddRef(ref release);
if (!release) throw new ObjectDisposedException(_handle.GetType().FullName);
var arrayPtr = FileArray(_ptr, out var count);
for (var i = 0; i < count; ++i)
{
yield return new File(FilePtr(arrayPtr, i));
}
for (var i = 0; i < count; ++i) yield return new File(FilePtr(arrayPtr, i));
}
finally
{
@@ -58,7 +56,7 @@ namespace Foodsoft.Alpm
{
get
{
return _handle.UseHandle(_ptr, (ptr) =>
return _handle.UseHandle(_ptr, ptr =>
{
var arrayPtr = FileArray(ptr, out var count);
if (index >= count || index < 0)
@@ -67,8 +65,8 @@ namespace Foodsoft.Alpm
});
}
}
[StructLayout(LayoutKind.Sequential)]
private readonly unsafe struct NativeFileList
{

View File

@@ -3,9 +3,6 @@ namespace Foodsoft.Alpm
public class FilePackage : Package
{
// ReSharper disable once SuggestBaseTypeForParameter
internal FilePackage(SafeFilePackageHandle handle) : base(handle)
{
}
internal FilePackage(SafeFilePackageHandle handle) : base(handle) { }
}
}

View File

@@ -1,20 +1,25 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
public sealed class Handle : IDisposable
{
private readonly SafeAlpmHandle _handle;
public Handle(string root, string dbpath)
{
_handle = alpm.alpm_initialize(root, dbpath, out var err);
if (_handle.IsInvalid)
{
throw new AlpmException(err);
}
if (_handle.IsInvalid) throw new AlpmException(err);
}
public Database LocalDB => ToDatabase(alpm.alpm_get_localdb(_handle));
public ICollection<string> CacheDirs
{
get =>
EnumerableWrapper.Create(_handle, alpm.alpm_option_get_cachedirs);
set => Detail.SetStringCollection(value, _handle, s => alpm.alpm_option_add_cachedir(_handle, s));
}
public void Dispose()
@@ -26,28 +31,29 @@ namespace Foodsoft.Alpm
{
// It's ok that the database pointer is kept outside atomic section, because the resource is actually
// managed by the alpm handle.
if (ptr == IntPtr.Zero)
{
throw new AlpmException(_handle);
}
if (ptr == IntPtr.Zero) throw new AlpmException(_handle);
return new Database(new SafeDatabaseHandle(ptr, _handle));
}
public Database LocalDB => ToDatabase(alpm.alpm_get_localdb(_handle));
public Database RegisterSyncDB(string treename, SigLevel sigLevel = 0) =>
ToDatabase(alpm.alpm_register_syncdb(_handle, treename, sigLevel));
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
public Database RegisterSyncDB(string treename, SigLevel sigLevel = 0)
{
get =>
EnumerableWrapper.Create(_handle, alpm.alpm_option_get_cachedirs);
set => Detail.SetStringCollection(value, _handle, (s) => alpm.alpm_option_add_cachedir(_handle, s));
return ToDatabase(alpm.alpm_register_syncdb(_handle, treename, sigLevel));
}
public bool ShouldIgnorePackage(Package pkg) => alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0;
public void AddCacheDir(string dir)
{
Detail.WrapError(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir));
}
public bool RemoveCacheDir(string dir)
{
return Detail.WrapErrorBool(_handle, () => alpm.alpm_option_add_cachedir(_handle, dir));
}
public bool ShouldIgnorePackage(Package pkg)
{
return alpm.alpm_pkg_should_ignore(_handle, pkg.Handle) == 0;
}
}
}

View File

@@ -20,10 +20,10 @@ namespace Foodsoft.Alpm
public enum ValidationType
{
Unknown = 0,
None = (1 << 0),
MD5Sum = (1 << 1),
SHA256Sum = (1 << 2),
Signature = (1 << 3)
None = 1 << 0,
MD5Sum = 1 << 1,
SHA256Sum = 1 << 2,
Signature = 1 << 3
}
public interface IPackageData : IDisposable
@@ -59,6 +59,6 @@ namespace Foodsoft.Alpm
public ValidationType Validation { get; }
public bool HasScriptlet { get; }
public long DownloadSize { get; }
public Database? DB { get; }
public Database? DB { get; }
}
}

View File

@@ -16,7 +16,10 @@ namespace Foodsoft.Alpm.Marshalling
Marshal.FreeCoTaskMem(pNativeData);
}
public int GetNativeDataSize() => -1;
public int GetNativeDataSize()
{
return -1;
}
public IntPtr MarshalManagedToNative(object? managedObj)
{

View File

@@ -18,7 +18,10 @@ namespace Foodsoft.Alpm.Marshalling
public void CleanUpNativeData(IntPtr pNativeData) { }
public int GetNativeDataSize() => -1;
public int GetNativeDataSize()
{
return -1;
}
public object MarshalNativeToManaged(IntPtr pNativeData)
{

View File

@@ -1,18 +1,17 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
public abstract class Package : IPackageData
{
internal SafePackageHandle Handle { get; }
internal Package(SafePackageHandle handle)
{
Handle = handle;
}
internal SafePackageHandle Handle { get; }
public string Filename => alpm.alpm_pkg_get_filename(Handle);
public string Base => alpm.alpm_pkg_get_base(Handle);
public string Name => alpm.alpm_pkg_get_name(Handle);
@@ -30,16 +29,22 @@ 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 IEnumerable<string> Licenses =>
EnumerableWrapper.Create(Handle, alpm.alpm_pkg_get_licenses);
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 IEnumerable<Depend> CheckDepends =>
EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_checkdepends);
public IEnumerable<Depend> MakeDepends =>
EnumerableWrapper.CreateForDepend(Handle, alpm.alpm_pkg_get_makedepends);
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);
@@ -50,28 +55,23 @@ namespace Foodsoft.Alpm
public bool HasScriptlet => alpm.alpm_pkg_has_scriptlet(Handle);
public long DownloadSize => alpm.alpm_pkg_download_size(Handle);
public bool CheckMD5Sum()
{
throw new NotImplementedException();
}
public virtual Database? DB => null;
public IEnumerator<Package> ComputeRequiredBy()
{
throw new NotImplementedException();
}
public IEnumerator<Package> ComputeOptionalFor()
{
throw new NotImplementedException();
}
public void Dispose()
{
Handle.Dispose();
}
public IEnumerable<Package> ComputeRequiredBy()
{
throw new NotImplementedException();
}
public IEnumerable<Package> ComputeOptionalFor()
{
throw new NotImplementedException();
}
public static int VersionCompare(string v1, string v2)
{
return alpm.alpm_pkg_vercmp(v1, v2);

View File

@@ -1,7 +1,6 @@
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using Foodsoft.Alpm;
namespace Foodsoft.Alpm
{
@@ -9,13 +8,18 @@ namespace Foodsoft.Alpm
{
private SafeAlpmHandle() : base(IntPtr.Zero, true) { }
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod]
protected override bool ReleaseHandle() => alpm.alpm_release(handle) == 0;
public override bool IsInvalid
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get => handle == IntPtr.Zero;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
protected override bool ReleaseHandle()
{
return alpm.alpm_release(handle) == 0;
}
}
}

View File

@@ -1,30 +1,15 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
internal sealed class SafeCachePackageHandle : SafePackageHandle
{
internal SafeAlpmHandle SafeAlpmHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get => SafeDatabaseHandle.SafeAlpmHandle;
}
internal SafeDatabaseHandle SafeDatabaseHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get;
} = null!;
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
internal SafeCachePackageHandle(IntPtr ptr, SafeDatabaseHandle parentHandle)
: base()
: base(parentHandle.SafeAlpmHandle)
{
var success = false;
@@ -43,6 +28,15 @@ namespace Foodsoft.Alpm
if (!success) throw new ObjectDisposedException(GetType().FullName);
}
internal SafeDatabaseHandle SafeDatabaseHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get;
} = null!;
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
protected override bool ReleaseHandle()
{
SafeDatabaseHandle.DangerousRelease();

View File

@@ -7,13 +7,6 @@ namespace Foodsoft.Alpm
{
internal sealed class SafeDatabaseHandle : SafeHandle
{
internal SafeAlpmHandle SafeAlpmHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get;
} = null!;
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
internal SafeDatabaseHandle(IntPtr dbPtr, SafeAlpmHandle safeAlpmHandle) : base(IntPtr.Zero, true)
@@ -35,18 +28,27 @@ namespace Foodsoft.Alpm
if (!success) throw new ObjectDisposedException(GetType().FullName);
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), PrePrepareMethod]
internal SafeAlpmHandle SafeAlpmHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get;
} = null!;
public override bool IsInvalid
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get => handle == IntPtr.Zero;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
protected override bool ReleaseHandle()
{
var err = alpm.alpm_db_unregister(handle);
SafeAlpmHandle.DangerousRelease();
return err == 0;
}
public override bool IsInvalid
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
get => handle == IntPtr.Zero;
}
}
}

View File

@@ -1,17 +1,14 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
internal class SafeFilePackageHandle : SafePackageHandle
{
internal SafeAlpmHandle SafeAlpmHandle { get; } = null!;
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
internal SafeFilePackageHandle(IntPtr ptr, SafeAlpmHandle parentHandle)
internal SafeFilePackageHandle(IntPtr ptr, SafeAlpmHandle parentHandle) : base(parentHandle)
{
var success = false;
@@ -20,20 +17,19 @@ namespace Foodsoft.Alpm
finally
{
parentHandle.DangerousAddRef(ref success);
if (success)
{
SafeAlpmHandle = parentHandle;
handle = ptr;
}
if (success) handle = ptr;
}
if (!success) throw new ObjectDisposedException(GetType().FullName);
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
protected override bool ReleaseHandle()
{
var err = alpm.alpm_pkg_free(handle);
SafeAlpmHandle.DangerousRelease();
return true;
return err == 0;
}
}
}

View File

@@ -1,52 +0,0 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
namespace Foodsoft.Alpm
{
internal sealed class SafeListHandle<TParent> : SafeHandle where TParent: SafeHandle
{
internal TParent ParentHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get;
} = null!;
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
[PrePrepareMethod]
internal SafeListHandle(IntPtr listPtr, TParent parentHandle)
: base(IntPtr.Zero, true)
{
var success = false;
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally
{
parentHandle.DangerousAddRef(ref success);
if (success)
{
ParentHandle = parentHandle;
handle = listPtr;
}
}
if (!success)
throw new ObjectDisposedException(GetType().FullName);
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
protected override bool ReleaseHandle()
{
ParentHandle.DangerousRelease();
return true;
}
public override bool IsInvalid
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
get => ParentHandle.IsInvalid;
}
}
}

View File

@@ -6,10 +6,22 @@ namespace Foodsoft.Alpm
{
internal abstract class SafePackageHandle : SafeHandle
{
protected SafePackageHandle() : base(IntPtr.Zero, true) { }
protected SafePackageHandle(SafeAlpmHandle safeAlpmHandle) : base(IntPtr.Zero, true)
{
SafeAlpmHandle = safeAlpmHandle;
}
internal SafeAlpmHandle SafeAlpmHandle
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get;
}
public override bool IsInvalid
{
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), PrePrepareMethod]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[PrePrepareMethod]
get => handle == IntPtr.Zero;
}
}

View File

@@ -16,6 +16,9 @@ namespace Foodsoft.Alpm
// ReSharper disable once InconsistentNaming
internal static class alpm
{
// ReSharper disable once InconsistentNaming
public delegate void alpm_fn_free(IntPtr ptr);
[DllImport(nameof(alpm))]
public static extern int alpm_pkg_should_ignore(SafeAlpmHandle handle, SafePackageHandle pkg);
@@ -122,7 +125,7 @@ namespace Foodsoft.Alpm
[DllImport(nameof(alpm))]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Return))]
public static extern string alpm_pkg_get_base64_sig(SafePackageHandle pkg);
[DllImport(nameof(alpm))]
public static extern ValidationType alpm_pkg_get_validation(SafePackageHandle pkg);
@@ -135,12 +138,16 @@ namespace Foodsoft.Alpm
[DllImport(nameof(alpm))]
public static extern int alpm_pkg_set_reason(SafePackageHandle pkg, InstallReason reason);
[DllImport(nameof(alpm))]
public static extern int alpm_pkg_checkmd5sum(SafePackageHandle pkg);
[DllImport(nameof(alpm))]
public static extern int alpm_pkg_free(IntPtr ptr);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_option_get_cachedirs(SafeAlpmHandle handle);
[DllImport(nameof(alpm))]
public static extern int alpm_option_add_cachedir(SafeAlpmHandle handle,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
@@ -152,11 +159,11 @@ namespace Foodsoft.Alpm
string cachedir);
[DllImport(nameof(alpm))]
public static extern ErrNo alpm_errno(SafeAlpmHandle handle);
public static extern Error alpm_errno(SafeAlpmHandle handle);
[DllImport(nameof(alpm))]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8Return))]
public static extern string alpm_strerror(ErrNo err);
public static extern string alpm_strerror(Error err);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_get_localdb(SafeAlpmHandle handle);
@@ -173,7 +180,7 @@ namespace Foodsoft.Alpm
public static extern int alpm_db_unregister_all_syncdbs(SafeAlpmHandle handle);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_list_add(IntPtr list, IntPtr item);
public static extern IntPtr alpm_list_append(ref IntPtr list, IntPtr item);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_list_append_strdup(ref IntPtr list,
@@ -189,9 +196,6 @@ namespace Foodsoft.Alpm
[DllImport(nameof(alpm))]
public static extern void alpm_list_free(IntPtr list);
// ReSharper disable once InconsistentNaming
public delegate void alpm_fn_free(IntPtr ptr);
[DllImport(nameof(alpm))]
public static extern void alpm_list_free_inner(IntPtr list, alpm_fn_free freeFn);
@@ -214,7 +218,7 @@ namespace Foodsoft.Alpm
public static extern SafeAlpmHandle alpm_initialize(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
string root, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
string dbpath, out ErrNo err);
string dbpath, out Error err);
[DllImport(nameof(alpm))]
public static extern int alpm_release(IntPtr handle);
@@ -257,6 +261,9 @@ namespace Foodsoft.Alpm
[DllImport(nameof(alpm))]
public static extern int alpm_db_set_usage(SafeDatabaseHandle db, Database.UsageFlags usage);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_db_search(SafeDatabaseHandle db, IntPtr needles);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_pkg_get_pkg(SafeDatabaseHandle db,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UTF8In))]
@@ -267,7 +274,7 @@ namespace Foodsoft.Alpm
[DllImport(nameof(alpm))]
public static extern int alpm_pkg_vercmp(string v1, string v2);
[DllImport(nameof(alpm))]
public static extern IntPtr alpm_find_satisfier(IntPtr pkgList, string depstring);
}

View File

@@ -1,122 +1,128 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Foodsoft.Alpm;
// ReSharper disable once UnusedType.Global
namespace Samples
{
[Example("installed")]
internal class Installed : IExample
{
private static string ModToStr(Depend.ModType modType)
{
return modType switch
{
Depend.ModType.Any => "",
Depend.ModType.Equal => "==",
Depend.ModType.GreaterThanOrEqual => ">=",
Depend.ModType.LessThanOrEqual => "<=",
Depend.ModType.GreaterThan => ">",
Depend.ModType.LessThan => "<",
_ => throw new ArgumentOutOfRangeException(nameof(modType), modType, null)
};
}
public int Run(string[] args)
{
using var h = new Handle("/", "/var/lib/pacman");
using var db = h.LocalDB;
foreach (var pkg in db.PackageCache)
using (pkg)
{
Console.WriteLine($"Size: {pkg.DownloadSize}");
foreach (var d in pkg.OptDepends)
{
if (d.Description.Length == 0) continue;
Console.WriteLine("dep({0}): {1} {2} {3} {4}", pkg.Name, d.Name, ModToStr(d.Mod), d.Version,
d.Description);
foreach (var f in pkg.Backup)
Console.WriteLine($"{f.Name} {f.Hash}");
}
}
return 0;
}
}
[Example("search")]
internal class Search : IExample
{
public int Run(string[] args)
{
using var h = new Handle("/", "/var/lib/pacman");
using var db = h.RegisterSyncDB("core");
db.Servers = new[] {"http://www.google.com"};
using var pkg = db.PackageCache.FindSatisfier("gcc=9.3.0-1");
Console.WriteLine($"{pkg?.Name} {pkg?.Version}");
return 0;
}
}
}
namespace Samples
{
internal static class Program
{
private static int Main(string[] args)
{
var examples = (from t in Assembly.GetExecutingAssembly().GetTypes()
let attribute = (Example?) t.GetCustomAttribute(typeof(Example))
where attribute != null
select new {Name = attribute.Name, Type = t}).ToImmutableDictionary((e) => e.Name);
if (args.Length < 1)
{
Console.Error.WriteLine("Sample");
foreach (var example in examples.Values)
{
Console.Error.WriteLine("{0}", example.Name);
}
return 1;
}
int ret;
try
{
ret = ((IExample) Activator.CreateInstance(examples[args[0]].Type)!).Run(args);
}
catch (AlpmException e)
{
Console.Error.WriteLine("{0}", e.Message);
return 1;
}
return ret;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
public class Example : Attribute
{
public string Name { get; }
public Example(string name)
{
Name = name;
}
}
public interface IExample
{
public int Run(string[] args);
}
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Foodsoft.Alpm;
// ReSharper disable once UnusedType.Global
namespace Samples
{
[Example("installed")]
internal class Installed : IExample
{
private static string ModToStr(Depend.ModType modType)
{
return modType switch
{
Depend.ModType.Any => "",
Depend.ModType.Equal => "==",
Depend.ModType.GreaterThanOrEqual => ">=",
Depend.ModType.LessThanOrEqual => "<=",
Depend.ModType.GreaterThan => ">",
Depend.ModType.LessThan => "<",
_ => throw new ArgumentOutOfRangeException(nameof(modType), modType, null)
};
}
public int Run(string[] args)
{
using var h = new Handle("/", "/var/lib/pacman");
using var db = h.LocalDB;
foreach (var pkg in db.PackageCache)
using (pkg)
{
Console.WriteLine($"Size: {pkg.DownloadSize}");
foreach (var d in pkg.OptDepends)
{
if (d.Description.Length == 0) continue;
Console.WriteLine("dep({0}): {1} {2} {3} {4}", pkg.Name, d.Name, ModToStr(d.Mod), d.Version,
d.Description);
foreach (var f in pkg.Backup)
Console.WriteLine($"{f.Name} {f.Hash}");
}
}
return 0;
}
}
[Example("search")]
internal class Search : IExample
{
public int Run(string[] args)
{
using var h = new Handle("/", "/var/lib/pacman");
using var db = h.RegisterSyncDB("core");
db.Servers = new[] {"http://www.google.com"};
//using var pkg = db.PackageCache.FindSatisfier("gcc=9.3.0-1");
var result = db.Search(new string[] {"gcc", "objc"});
foreach (var pkg in result)
using (pkg)
{
Console.WriteLine($"{pkg?.Name} {pkg?.Version}");
}
return 0;
}
}
}
namespace Samples
{
internal static class Program
{
private static int Main(string[] args)
{
var examples = (from t in Assembly.GetExecutingAssembly().GetTypes()
let attribute = (Example?) t.GetCustomAttribute(typeof(Example))
where attribute != null
select new {Name = attribute.Name, Type = t}).ToImmutableDictionary((e) => e.Name);
if (args.Length < 1)
{
Console.Error.WriteLine("Sample");
foreach (var example in examples.Values)
{
Console.Error.WriteLine("{0}", example.Name);
}
return 1;
}
int ret;
try
{
ret = ((IExample) Activator.CreateInstance(examples[args[0]].Type)!).Run(args);
}
catch (AlpmException e)
{
Console.Error.WriteLine("{0}", e.Message);
return 1;
}
return ret;
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
public class Example : Attribute
{
public string Name { get; }
public Example(string name)
{
Name = name;
}
}
public interface IExample
{
public int Run(string[] args);
}
}