Files
DotNetAlpm/Alpm/Database.cs
2020-05-01 05:08:04 -04:00

144 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
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;
}
// 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);
set
{
var listPtr = IntPtr.Zero;
var success = false;
var err = 0;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var s in value)
if (alpm.alpm_list_append_strdup(ref listPtr, s) == IntPtr.Zero)
throw new AlpmException(ErrorCode.Memory);
success = true;
}
finally
{
if (success)
err = alpm.alpm_db_set_servers(_handle, listPtr);
else
alpm.alpm_list_free(listPtr);
}
if (err != 0)
throw new AlpmException(_handle.SafeAlpmHandle);
}
}
public string Name => alpm.alpm_db_get_name(_handle);
public SigLevel SigLevel => alpm.alpm_db_get_siglevel(_handle);
public ErrorCode Valid =>
alpm.alpm_db_get_valid(_handle) != 0 ? alpm.alpm_errno(_handle.SafeAlpmHandle) : ErrorCode.OK;
public CachePackageList PackageCache
{
get
{
var listPtr = alpm.alpm_db_get_pkgcache(_handle);
if (listPtr == IntPtr.Zero)
throw new AlpmException(_handle.SafeAlpmHandle);
return new CachePackageList(listPtr, _handle, this);
}
}
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 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 == ErrorCode.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 != ErrorCode.OK)
throw new AlpmException(errNo);
}
return new CachePackageList(result, _handle, this);
}
}
}