mirror of
https://github.com/rust-lang/cargo
synced 2024-08-24 18:15:45 +00:00
Don't try to compile cargo-credential-gnome-secret on non-Linux platforms.
This commit is contained in:
parent
be42872358
commit
21ccfb8fa6
|
@ -1,3 +1,8 @@
|
|||
fn main() {
|
||||
pkg_config::probe_library("libsecret-1").unwrap();
|
||||
if cfg!(target_os = "linux") {
|
||||
// TODO: Consider ignoring errors when libsecret is not installed and
|
||||
// switching the impl to UnsupportedCredential (possibly along with a
|
||||
// warning?).
|
||||
pkg_config::probe_library("libsecret-1").unwrap();
|
||||
}
|
||||
}
|
||||
|
|
190
credential/cargo-credential-gnome-secret/src/libsecret.rs
Normal file
190
credential/cargo-credential-gnome-secret/src/libsecret.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
//! Implementation of the libsecret credential helper.
|
||||
|
||||
use cargo_credential::{Credential, Error};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type gchar = c_char;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type gboolean = c_int;
|
||||
|
||||
type GQuark = u32;
|
||||
|
||||
#[repr(C)]
|
||||
struct GError {
|
||||
domain: GQuark,
|
||||
code: c_int,
|
||||
message: *mut gchar,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct GCancellable {
|
||||
_private: [u8; 0],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct SecretSchema {
|
||||
name: *const gchar,
|
||||
flags: SecretSchemaFlags,
|
||||
attributes: [SecretSchemaAttribute; 32],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct SecretSchemaAttribute {
|
||||
name: *const gchar,
|
||||
attr_type: SecretSchemaAttributeType,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
enum SecretSchemaFlags {
|
||||
None = 0,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
enum SecretSchemaAttributeType {
|
||||
String = 0,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn secret_password_store_sync(
|
||||
schema: *const SecretSchema,
|
||||
collection: *const gchar,
|
||||
label: *const gchar,
|
||||
password: *const gchar,
|
||||
cancellable: *mut GCancellable,
|
||||
error: *mut *mut GError,
|
||||
...
|
||||
) -> gboolean;
|
||||
fn secret_password_clear_sync(
|
||||
schema: *const SecretSchema,
|
||||
cancellable: *mut GCancellable,
|
||||
error: *mut *mut GError,
|
||||
...
|
||||
) -> gboolean;
|
||||
fn secret_password_lookup_sync(
|
||||
schema: *const SecretSchema,
|
||||
cancellable: *mut GCancellable,
|
||||
error: *mut *mut GError,
|
||||
...
|
||||
) -> *mut gchar;
|
||||
}
|
||||
|
||||
pub struct GnomeSecret;
|
||||
|
||||
fn label(index_url: &str) -> CString {
|
||||
CString::new(format!("cargo-registry:{}", index_url)).unwrap()
|
||||
}
|
||||
|
||||
fn schema() -> SecretSchema {
|
||||
let mut attributes = [SecretSchemaAttribute {
|
||||
name: null(),
|
||||
attr_type: SecretSchemaAttributeType::String,
|
||||
}; 32];
|
||||
attributes[0] = SecretSchemaAttribute {
|
||||
name: b"url\0".as_ptr() as *const gchar,
|
||||
attr_type: SecretSchemaAttributeType::String,
|
||||
};
|
||||
SecretSchema {
|
||||
name: b"org.rust-lang.cargo.registry\0".as_ptr() as *const gchar,
|
||||
flags: SecretSchemaFlags::None,
|
||||
attributes,
|
||||
}
|
||||
}
|
||||
|
||||
impl Credential for GnomeSecret {
|
||||
fn name(&self) -> &'static str {
|
||||
env!("CARGO_PKG_NAME")
|
||||
}
|
||||
|
||||
fn get(&self, index_url: &str) -> Result<String, Error> {
|
||||
let mut error: *mut GError = null_mut();
|
||||
let attr_url = CString::new("url").unwrap();
|
||||
let index_url_c = CString::new(index_url).unwrap();
|
||||
let schema = schema();
|
||||
unsafe {
|
||||
let token_c = secret_password_lookup_sync(
|
||||
&schema,
|
||||
null_mut(),
|
||||
&mut error,
|
||||
attr_url.as_ptr(),
|
||||
index_url_c.as_ptr(),
|
||||
null() as *const gchar,
|
||||
);
|
||||
if !error.is_null() {
|
||||
return Err(format!(
|
||||
"failed to get token: {}",
|
||||
CStr::from_ptr((*error).message).to_str()?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
if token_c.is_null() {
|
||||
return Err(format!("cannot find token for {}", index_url).into());
|
||||
}
|
||||
let token = CStr::from_ptr(token_c)
|
||||
.to_str()
|
||||
.map_err(|e| format!("expected utf8 token: {}", e))?
|
||||
.to_string();
|
||||
Ok(token)
|
||||
}
|
||||
}
|
||||
|
||||
fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> {
|
||||
let label = label(name.unwrap_or(index_url));
|
||||
let token = CString::new(token).unwrap();
|
||||
let mut error: *mut GError = null_mut();
|
||||
let attr_url = CString::new("url").unwrap();
|
||||
let index_url_c = CString::new(index_url).unwrap();
|
||||
let schema = schema();
|
||||
unsafe {
|
||||
secret_password_store_sync(
|
||||
&schema,
|
||||
b"default\0".as_ptr() as *const gchar,
|
||||
label.as_ptr(),
|
||||
token.as_ptr(),
|
||||
null_mut(),
|
||||
&mut error,
|
||||
attr_url.as_ptr(),
|
||||
index_url_c.as_ptr(),
|
||||
null() as *const gchar,
|
||||
);
|
||||
if !error.is_null() {
|
||||
return Err(format!(
|
||||
"failed to store token: {}",
|
||||
CStr::from_ptr((*error).message).to_str()?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn erase(&self, index_url: &str) -> Result<(), Error> {
|
||||
let schema = schema();
|
||||
let mut error: *mut GError = null_mut();
|
||||
let attr_url = CString::new("url").unwrap();
|
||||
let index_url_c = CString::new(index_url).unwrap();
|
||||
unsafe {
|
||||
secret_password_clear_sync(
|
||||
&schema,
|
||||
null_mut(),
|
||||
&mut error,
|
||||
attr_url.as_ptr(),
|
||||
index_url_c.as_ptr(),
|
||||
null() as *const gchar,
|
||||
);
|
||||
if !error.is_null() {
|
||||
return Err(format!(
|
||||
"failed to erase token: {}",
|
||||
CStr::from_ptr((*error).message).to_str()?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -1,193 +1,11 @@
|
|||
//! Cargo registry gnome libsecret credential process.
|
||||
|
||||
use cargo_credential::{Credential, Error};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type gchar = c_char;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
type gboolean = c_int;
|
||||
|
||||
type GQuark = u32;
|
||||
|
||||
#[repr(C)]
|
||||
struct GError {
|
||||
domain: GQuark,
|
||||
code: c_int,
|
||||
message: *mut gchar,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct GCancellable {
|
||||
_private: [u8; 0],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct SecretSchema {
|
||||
name: *const gchar,
|
||||
flags: SecretSchemaFlags,
|
||||
attributes: [SecretSchemaAttribute; 32],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
struct SecretSchemaAttribute {
|
||||
name: *const gchar,
|
||||
attr_type: SecretSchemaAttributeType,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
enum SecretSchemaFlags {
|
||||
None = 0,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
enum SecretSchemaAttributeType {
|
||||
String = 0,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn secret_password_store_sync(
|
||||
schema: *const SecretSchema,
|
||||
collection: *const gchar,
|
||||
label: *const gchar,
|
||||
password: *const gchar,
|
||||
cancellable: *mut GCancellable,
|
||||
error: *mut *mut GError,
|
||||
...
|
||||
) -> gboolean;
|
||||
fn secret_password_clear_sync(
|
||||
schema: *const SecretSchema,
|
||||
cancellable: *mut GCancellable,
|
||||
error: *mut *mut GError,
|
||||
...
|
||||
) -> gboolean;
|
||||
fn secret_password_lookup_sync(
|
||||
schema: *const SecretSchema,
|
||||
cancellable: *mut GCancellable,
|
||||
error: *mut *mut GError,
|
||||
...
|
||||
) -> *mut gchar;
|
||||
}
|
||||
|
||||
struct GnomeSecret;
|
||||
|
||||
fn label(index_url: &str) -> CString {
|
||||
CString::new(format!("cargo-registry:{}", index_url)).unwrap()
|
||||
}
|
||||
|
||||
fn schema() -> SecretSchema {
|
||||
let mut attributes = [SecretSchemaAttribute {
|
||||
name: null(),
|
||||
attr_type: SecretSchemaAttributeType::String,
|
||||
}; 32];
|
||||
attributes[0] = SecretSchemaAttribute {
|
||||
name: b"url\0".as_ptr() as *const gchar,
|
||||
attr_type: SecretSchemaAttributeType::String,
|
||||
};
|
||||
SecretSchema {
|
||||
name: b"org.rust-lang.cargo.registry\0".as_ptr() as *const gchar,
|
||||
flags: SecretSchemaFlags::None,
|
||||
attributes,
|
||||
}
|
||||
}
|
||||
|
||||
impl Credential for GnomeSecret {
|
||||
fn name(&self) -> &'static str {
|
||||
env!("CARGO_PKG_NAME")
|
||||
}
|
||||
|
||||
fn get(&self, index_url: &str) -> Result<String, Error> {
|
||||
let mut error: *mut GError = null_mut();
|
||||
let attr_url = CString::new("url").unwrap();
|
||||
let index_url_c = CString::new(index_url).unwrap();
|
||||
let schema = schema();
|
||||
unsafe {
|
||||
let token_c = secret_password_lookup_sync(
|
||||
&schema,
|
||||
null_mut(),
|
||||
&mut error,
|
||||
attr_url.as_ptr(),
|
||||
index_url_c.as_ptr(),
|
||||
null() as *const gchar,
|
||||
);
|
||||
if !error.is_null() {
|
||||
return Err(format!(
|
||||
"failed to get token: {}",
|
||||
CStr::from_ptr((*error).message).to_str()?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
if token_c.is_null() {
|
||||
return Err(format!("cannot find token for {}", index_url).into());
|
||||
}
|
||||
let token = CStr::from_ptr(token_c)
|
||||
.to_str()
|
||||
.map_err(|e| format!("expected utf8 token: {}", e))?
|
||||
.to_string();
|
||||
Ok(token)
|
||||
}
|
||||
}
|
||||
|
||||
fn store(&self, index_url: &str, token: &str, name: Option<&str>) -> Result<(), Error> {
|
||||
let label = label(name.unwrap_or(index_url));
|
||||
let token = CString::new(token).unwrap();
|
||||
let mut error: *mut GError = null_mut();
|
||||
let attr_url = CString::new("url").unwrap();
|
||||
let index_url_c = CString::new(index_url).unwrap();
|
||||
let schema = schema();
|
||||
unsafe {
|
||||
secret_password_store_sync(
|
||||
&schema,
|
||||
b"default\0".as_ptr() as *const gchar,
|
||||
label.as_ptr(),
|
||||
token.as_ptr(),
|
||||
null_mut(),
|
||||
&mut error,
|
||||
attr_url.as_ptr(),
|
||||
index_url_c.as_ptr(),
|
||||
null() as *const gchar,
|
||||
);
|
||||
if !error.is_null() {
|
||||
return Err(format!(
|
||||
"failed to store token: {}",
|
||||
CStr::from_ptr((*error).message).to_str()?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn erase(&self, index_url: &str) -> Result<(), Error> {
|
||||
let schema = schema();
|
||||
let mut error: *mut GError = null_mut();
|
||||
let attr_url = CString::new("url").unwrap();
|
||||
let index_url_c = CString::new(index_url).unwrap();
|
||||
unsafe {
|
||||
secret_password_clear_sync(
|
||||
&schema,
|
||||
null_mut(),
|
||||
&mut error,
|
||||
attr_url.as_ptr(),
|
||||
index_url_c.as_ptr(),
|
||||
null() as *const gchar,
|
||||
);
|
||||
if !error.is_null() {
|
||||
return Err(format!(
|
||||
"failed to erase token: {}",
|
||||
CStr::from_ptr((*error).message).to_str()?
|
||||
)
|
||||
.into());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
mod libsecret;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use cargo_credential::UnsupportedCredential as GnomeSecret;
|
||||
#[cfg(target_os = "linux")]
|
||||
use libsecret::GnomeSecret;
|
||||
|
||||
fn main() {
|
||||
cargo_credential::main(GnomeSecret);
|
||||
|
|
Loading…
Reference in a new issue