Compare commits
10 Commits
411fefc663
...
a80ba30877
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a80ba30877 | ||
|
|
86a5091555 | ||
|
|
507ffe472d | ||
|
|
f315eba8d4 | ||
|
|
5edd8250f5 | ||
|
|
4a25bff861 | ||
|
|
0b71f80254 | ||
|
|
a614bd3f44 | ||
|
|
4a9cb0ddac | ||
|
|
57b1e7709c |
1357
0001-add-loongarch64-support-for-ffi.patch
Normal file
1357
0001-add-loongarch64-support-for-ffi.patch
Normal file
File diff suppressed because one or more lines are too long
114
0002-Add-types.conf-for-riscv64-linux.patch
Normal file
114
0002-Add-types.conf-for-riscv64-linux.patch
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
Source: commit/3a280f70a36b56239d149d6205d20933151a2af3
|
||||||
|
Author: Andreas Schwab <schwab@suse.de>
|
||||||
|
Date: Thu Feb 25 12:17:32 2021 +0100
|
||||||
|
|
||||||
|
Add types.conf for riscv64-linux
|
||||||
|
|
||||||
|
diff -Nur a/lib/ffi/platform/riscv64-linux/types.conf b/lib/ffi/platform/riscv64-linux/types.conf
|
||||||
|
--- a/lib/ffi/platform/riscv64-linux/types.conf 1970-01-01 08:00:00.000000000 +0800
|
||||||
|
+++ b/lib/ffi/platform/riscv64-linux/types.conf 2022-02-28 12:10:35.462892020 +0800
|
||||||
|
@@ -0,0 +1,104 @@
|
||||||
|
+rbx.platform.typedef.*__caddr_t = char
|
||||||
|
+rbx.platform.typedef.*__qaddr_t = long
|
||||||
|
+rbx.platform.typedef.__blkcnt64_t = long
|
||||||
|
+rbx.platform.typedef.__blkcnt_t = long
|
||||||
|
+rbx.platform.typedef.__blksize_t = int
|
||||||
|
+rbx.platform.typedef.__clock_t = long
|
||||||
|
+rbx.platform.typedef.__clockid_t = int
|
||||||
|
+rbx.platform.typedef.__daddr_t = int
|
||||||
|
+rbx.platform.typedef.__dev_t = ulong
|
||||||
|
+rbx.platform.typedef.__fd_mask = long
|
||||||
|
+rbx.platform.typedef.__fsblkcnt64_t = ulong
|
||||||
|
+rbx.platform.typedef.__fsblkcnt_t = ulong
|
||||||
|
+rbx.platform.typedef.__fsfilcnt64_t = ulong
|
||||||
|
+rbx.platform.typedef.__fsfilcnt_t = ulong
|
||||||
|
+rbx.platform.typedef.__fsword_t = long
|
||||||
|
+rbx.platform.typedef.__gid_t = uint
|
||||||
|
+rbx.platform.typedef.__id_t = uint
|
||||||
|
+rbx.platform.typedef.__ino64_t = ulong
|
||||||
|
+rbx.platform.typedef.__ino_t = ulong
|
||||||
|
+rbx.platform.typedef.__int16_t = short
|
||||||
|
+rbx.platform.typedef.__int32_t = int
|
||||||
|
+rbx.platform.typedef.__int64_t = long
|
||||||
|
+rbx.platform.typedef.__int8_t = char
|
||||||
|
+rbx.platform.typedef.__intptr_t = long
|
||||||
|
+rbx.platform.typedef.__key_t = int
|
||||||
|
+rbx.platform.typedef.__loff_t = long
|
||||||
|
+rbx.platform.typedef.__mode_t = uint
|
||||||
|
+rbx.platform.typedef.__nlink_t = uint
|
||||||
|
+rbx.platform.typedef.__off64_t = long
|
||||||
|
+rbx.platform.typedef.__off_t = long
|
||||||
|
+rbx.platform.typedef.__pid_t = int
|
||||||
|
+rbx.platform.typedef.__priority_which_t = int
|
||||||
|
+rbx.platform.typedef.__quad_t = long
|
||||||
|
+rbx.platform.typedef.__rlim64_t = ulong
|
||||||
|
+rbx.platform.typedef.__rlim_t = ulong
|
||||||
|
+rbx.platform.typedef.__rlimit_resource_t = int
|
||||||
|
+rbx.platform.typedef.__rusage_who_t = int
|
||||||
|
+rbx.platform.typedef.__sig_atomic_t = int
|
||||||
|
+rbx.platform.typedef.__socklen_t = uint
|
||||||
|
+rbx.platform.typedef.__ssize_t = long
|
||||||
|
+rbx.platform.typedef.__suseconds_t = long
|
||||||
|
+rbx.platform.typedef.__syscall_slong_t = long
|
||||||
|
+rbx.platform.typedef.__syscall_ulong_t = ulong
|
||||||
|
+rbx.platform.typedef.__time_t = long
|
||||||
|
+rbx.platform.typedef.__timer_t = pointer
|
||||||
|
+rbx.platform.typedef.__u_char = uchar
|
||||||
|
+rbx.platform.typedef.__u_int = uint
|
||||||
|
+rbx.platform.typedef.__u_long = ulong
|
||||||
|
+rbx.platform.typedef.__u_quad_t = ulong
|
||||||
|
+rbx.platform.typedef.__u_short = ushort
|
||||||
|
+rbx.platform.typedef.__uid_t = uint
|
||||||
|
+rbx.platform.typedef.__uint16_t = ushort
|
||||||
|
+rbx.platform.typedef.__uint32_t = uint
|
||||||
|
+rbx.platform.typedef.__uint64_t = ulong
|
||||||
|
+rbx.platform.typedef.__uint8_t = uchar
|
||||||
|
+rbx.platform.typedef.__useconds_t = uint
|
||||||
|
+rbx.platform.typedef.blkcnt_t = long
|
||||||
|
+rbx.platform.typedef.blksize_t = int
|
||||||
|
+rbx.platform.typedef.clock_t = long
|
||||||
|
+rbx.platform.typedef.clockid_t = int
|
||||||
|
+rbx.platform.typedef.daddr_t = int
|
||||||
|
+rbx.platform.typedef.dev_t = ulong
|
||||||
|
+rbx.platform.typedef.fd_mask = long
|
||||||
|
+rbx.platform.typedef.fsblkcnt_t = ulong
|
||||||
|
+rbx.platform.typedef.fsfilcnt_t = ulong
|
||||||
|
+rbx.platform.typedef.gid_t = uint
|
||||||
|
+rbx.platform.typedef.id_t = uint
|
||||||
|
+rbx.platform.typedef.ino_t = ulong
|
||||||
|
+rbx.platform.typedef.int16_t = short
|
||||||
|
+rbx.platform.typedef.int32_t = int
|
||||||
|
+rbx.platform.typedef.int64_t = long
|
||||||
|
+rbx.platform.typedef.int8_t = char
|
||||||
|
+rbx.platform.typedef.key_t = int
|
||||||
|
+rbx.platform.typedef.loff_t = long
|
||||||
|
+rbx.platform.typedef.mode_t = uint
|
||||||
|
+rbx.platform.typedef.nlink_t = uint
|
||||||
|
+rbx.platform.typedef.off_t = long
|
||||||
|
+rbx.platform.typedef.pid_t = int
|
||||||
|
+rbx.platform.typedef.pthread_key_t = uint
|
||||||
|
+rbx.platform.typedef.pthread_once_t = int
|
||||||
|
+rbx.platform.typedef.pthread_t = ulong
|
||||||
|
+rbx.platform.typedef.quad_t = long
|
||||||
|
+rbx.platform.typedef.register_t = long
|
||||||
|
+rbx.platform.typedef.rlim_t = ulong
|
||||||
|
+rbx.platform.typedef.sa_family_t = ushort
|
||||||
|
+rbx.platform.typedef.size_t = ulong
|
||||||
|
+rbx.platform.typedef.socklen_t = uint
|
||||||
|
+rbx.platform.typedef.ssize_t = long
|
||||||
|
+rbx.platform.typedef.suseconds_t = long
|
||||||
|
+rbx.platform.typedef.time_t = long
|
||||||
|
+rbx.platform.typedef.timer_t = pointer
|
||||||
|
+rbx.platform.typedef.u_char = uchar
|
||||||
|
+rbx.platform.typedef.u_int = uint
|
||||||
|
+rbx.platform.typedef.u_int16_t = ushort
|
||||||
|
+rbx.platform.typedef.u_int32_t = uint
|
||||||
|
+rbx.platform.typedef.u_int64_t = ulong
|
||||||
|
+rbx.platform.typedef.u_int8_t = uchar
|
||||||
|
+rbx.platform.typedef.u_long = ulong
|
||||||
|
+rbx.platform.typedef.u_quad_t = ulong
|
||||||
|
+rbx.platform.typedef.u_short = ushort
|
||||||
|
+rbx.platform.typedef.uid_t = uint
|
||||||
|
+rbx.platform.typedef.uint = uint
|
||||||
|
+rbx.platform.typedef.ulong = ulong
|
||||||
|
+rbx.platform.typedef.ushort = ushort
|
||||||
BIN
1.10.0.tar.gz
Normal file
BIN
1.10.0.tar.gz
Normal file
Binary file not shown.
150
Remove-taint-support.patch
Normal file
150
Remove-taint-support.patch
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
diff -Nur a/ext/ffi_c/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c
|
||||||
|
--- a/ext/ffi_c/AbstractMemory.c 2022-01-26 16:51:07.093052671 +0800
|
||||||
|
+++ b/ext/ffi_c/AbstractMemory.c 2022-01-26 16:50:35.108522777 +0800
|
||||||
|
@@ -417,7 +417,7 @@
|
||||||
|
checkBounds(ptr, off, len);
|
||||||
|
|
||||||
|
end = memchr(ptr->address + off, 0, len);
|
||||||
|
- return rb_tainted_str_new((char *) ptr->address + off,
|
||||||
|
+ return rb_str_new((char *) ptr->address + off,
|
||||||
|
(end != NULL ? end - ptr->address - off : len));
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -453,7 +453,7 @@
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
const char* strptr = *((const char**) (ptr->address + off) + i);
|
||||||
|
- rb_ary_push(retVal, (strptr == NULL ? Qnil : rb_tainted_str_new2(strptr)));
|
||||||
|
+ rb_ary_push(retVal, (strptr == NULL ? Qnil : rb_str_new2(strptr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
@@ -463,7 +463,7 @@
|
||||||
|
if (strptr == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- rb_ary_push(retVal, rb_tainted_str_new2(strptr));
|
||||||
|
+ rb_ary_push(retVal, rb_str_new2(strptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -542,7 +542,7 @@
|
||||||
|
checkRead(ptr);
|
||||||
|
checkBounds(ptr, off, len);
|
||||||
|
|
||||||
|
- return rb_tainted_str_new((char *) ptr->address + off, len);
|
||||||
|
+ return rb_str_new((char *) ptr->address + off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -583,10 +583,6 @@
|
||||||
|
checkWrite(ptr);
|
||||||
|
checkBounds(ptr, off, len);
|
||||||
|
|
||||||
|
- if (rb_safe_level() >= 1 && OBJ_TAINTED(str)) {
|
||||||
|
- rb_raise(rb_eSecurityError, "Writing unsafe string to memory");
|
||||||
|
- return Qnil;
|
||||||
|
- }
|
||||||
|
memcpy(ptr->address + off, RSTRING_PTR(str) + idx, len);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
@@ -718,7 +714,7 @@
|
||||||
|
memcpy(&tmp, ptr->address + offset, sizeof(tmp));
|
||||||
|
}
|
||||||
|
|
||||||
|
- return tmp != NULL ? rb_tainted_str_new2(tmp) : Qnil;
|
||||||
|
+ return tmp != NULL ? rb_str_new2(tmp) : Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
diff -Nur a/ext/ffi_c/Call.c b/ext/ffi_c/Call.c
|
||||||
|
--- a/ext/ffi_c/Call.c 2022-01-26 16:51:07.093052671 +0800
|
||||||
|
+++ b/ext/ffi_c/Call.c 2022-01-26 16:50:38.876585203 +0800
|
||||||
|
@@ -300,10 +300,6 @@
|
||||||
|
param->ptr = NULL;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
- if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) {
|
||||||
|
- rb_raise(rb_eSecurityError, "Unsafe string parameter");
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
param->ptr = StringValueCStr(argv[argidx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff -Nur a/ext/ffi_c/DynamicLibrary.c b/ext/ffi_c/DynamicLibrary.c
|
||||||
|
--- a/ext/ffi_c/DynamicLibrary.c 2022-01-26 16:51:07.097052737 +0800
|
||||||
|
+++ b/ext/ffi_c/DynamicLibrary.c 2022-01-26 16:50:35.108522777 +0800
|
||||||
|
@@ -164,7 +164,7 @@
|
||||||
|
{
|
||||||
|
char errmsg[1024];
|
||||||
|
dl_error(errmsg, sizeof(errmsg));
|
||||||
|
- return rb_tainted_str_new2(errmsg);
|
||||||
|
+ return rb_str_new2(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
diff -Nur a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c
|
||||||
|
--- a/ext/ffi_c/Function.c 2022-01-26 16:51:07.097052737 +0800
|
||||||
|
+++ b/ext/ffi_c/Function.c 2022-01-26 16:50:42.484644979 +0800
|
||||||
|
@@ -808,7 +808,7 @@
|
||||||
|
param = rbffi_longdouble_new(*(long double *) parameters[i]);
|
||||||
|
break;
|
||||||
|
case NATIVE_STRING:
|
||||||
|
- param = (*(void **) parameters[i] != NULL) ? rb_tainted_str_new2(*(char **) parameters[i]) : Qnil;
|
||||||
|
+ param = (*(void **) parameters[i] != NULL) ? rb_str_new2(*(char **) parameters[i]) : Qnil;
|
||||||
|
break;
|
||||||
|
case NATIVE_POINTER:
|
||||||
|
param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
|
||||||
|
diff -Nur a/ext/ffi_c/Types.c b/ext/ffi_c/Types.c
|
||||||
|
--- a/ext/ffi_c/Types.c 2022-01-26 16:51:07.105052870 +0800
|
||||||
|
+++ b/ext/ffi_c/Types.c 2022-01-26 16:50:35.108522777 +0800
|
||||||
|
@@ -80,7 +80,7 @@
|
||||||
|
return rbffi_longdouble_new(*(long double *) ptr);
|
||||||
|
|
||||||
|
case NATIVE_STRING:
|
||||||
|
- return (*(void **) ptr != NULL) ? rb_tainted_str_new2(*(char **) ptr) : Qnil;
|
||||||
|
+ return (*(void **) ptr != NULL) ? rb_str_new2(*(char **) ptr) : Qnil;
|
||||||
|
case NATIVE_POINTER:
|
||||||
|
return rbffi_Pointer_NewInstance(*(void **) ptr);
|
||||||
|
case NATIVE_BOOL:
|
||||||
|
diff -Nur a/spec/ffi/string_spec.rb b/spec/ffi/string_spec.rb
|
||||||
|
--- a/spec/ffi/string_spec.rb 2019-01-06 22:25:53.000000000 +0800
|
||||||
|
+++ b/spec/ffi/string_spec.rb 2022-01-26 15:22:39.289071937 +0800
|
||||||
|
@@ -15,37 +15,11 @@
|
||||||
|
attach_function :string_null, [ ], :string
|
||||||
|
end
|
||||||
|
|
||||||
|
- it "MemoryPointer#get_string returns a tainted string" do
|
||||||
|
- mp = FFI::MemoryPointer.new 1024
|
||||||
|
- mp.put_string(0, "test\0")
|
||||||
|
- str = mp.get_string(0)
|
||||||
|
- expect(str.tainted?).to be true
|
||||||
|
- end
|
||||||
|
-
|
||||||
|
- it "String returned by a method is tainted" do
|
||||||
|
- mp = FFI::MemoryPointer.new :pointer
|
||||||
|
- sp = FFI::MemoryPointer.new 1024
|
||||||
|
- sp.put_string(0, "test")
|
||||||
|
- mp.put_pointer(0, sp)
|
||||||
|
- str = StrLibTest.ptr_ret_pointer(mp, 0)
|
||||||
|
- expect(str).to eq("test")
|
||||||
|
- expect(str).to be_tainted
|
||||||
|
- end
|
||||||
|
-
|
||||||
|
it "Poison null byte raises error" do
|
||||||
|
s = "123\0abc"
|
||||||
|
expect { StrLibTest.string_equals(s, s) }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
- it "Tainted String parameter should throw a SecurityError" do
|
||||||
|
- $SAFE = 1
|
||||||
|
- str = "test"
|
||||||
|
- str.taint
|
||||||
|
- begin
|
||||||
|
- expect(LibTest.string_equals(str, str)).to be false
|
||||||
|
- rescue SecurityError
|
||||||
|
- end
|
||||||
|
- end if false
|
||||||
|
it "casts nil as NULL pointer" do
|
||||||
|
expect(StrLibTest.string_dummy(nil)).to be_nil
|
||||||
|
end
|
||||||
42
ffi-1.10.0-loongarch64.gemspec
Normal file
42
ffi-1.10.0-loongarch64.gemspec
Normal file
File diff suppressed because one or more lines are too long
BIN
ffi-1.10.0.gem
Normal file
BIN
ffi-1.10.0.gem
Normal file
Binary file not shown.
102
rubygem-ffi.spec
Normal file
102
rubygem-ffi.spec
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
%global gem_name ffi
|
||||||
|
Name: rubygem-%{gem_name}
|
||||||
|
Version: 1.10.0
|
||||||
|
Release: 5
|
||||||
|
Summary: FFI Extensions for Ruby
|
||||||
|
License: BSD-3-Clause and MIT
|
||||||
|
URL: https://www.github.com/ffi/ffi
|
||||||
|
Source0: https://rubygems.org/gems/%{gem_name}-%{version}.gem
|
||||||
|
Source1: https://www.github.com/ffi/%{gem_name}/archive/%{version}.tar.gz
|
||||||
|
Source2: ffi-1.10.0-loongarch64.gemspec
|
||||||
|
Patch0: Remove-taint-support.patch
|
||||||
|
Patch1: 0001-add-loongarch64-support-for-ffi.patch
|
||||||
|
Patch2: 0002-Add-types.conf-for-riscv64-linux.patch
|
||||||
|
BuildRequires: ruby(release) rubygems-devel ruby-devel gcc libffi-devel rubygem(rspec)
|
||||||
|
%description
|
||||||
|
Ruby-FFI is a ruby extension for programmatically loading dynamic
|
||||||
|
libraries, binding functions within them, and calling those functions
|
||||||
|
from Ruby code. Moreover, a Ruby-FFI extension works without changes
|
||||||
|
on Ruby and JRuby. Discover why should you write your next extension
|
||||||
|
using Ruby-FFI here[http://wiki.github.com/ffi/ffi/why-use-ffi].
|
||||||
|
|
||||||
|
%package doc
|
||||||
|
Summary: Documentation for %{name}
|
||||||
|
Requires: %{name} = %{version}-%{release}
|
||||||
|
BuildArch: noarch
|
||||||
|
%description doc
|
||||||
|
Documentation for %{name}.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q -n %{gem_name}-%{version} -b 1
|
||||||
|
ln -s %{gem_name}-%{version}/test test
|
||||||
|
ln -s %{gem_name}-%{version}/spec spec
|
||||||
|
%patch0 -p1
|
||||||
|
%ifarch loongarch64
|
||||||
|
%patch1 -p1
|
||||||
|
%endif
|
||||||
|
%patch2 -p1
|
||||||
|
|
||||||
|
%build
|
||||||
|
%ifarch loongarch64
|
||||||
|
gem build %{SOURCE2}
|
||||||
|
%else
|
||||||
|
gem build ../%{gem_name}-%{version}.gemspec
|
||||||
|
%endif
|
||||||
|
%gem_install
|
||||||
|
|
||||||
|
%install
|
||||||
|
mkdir -p %{buildroot}%{gem_dir}
|
||||||
|
%ifarch riscv64
|
||||||
|
cp -r lib/ffi/platform/riscv64-linux/ .%{gem_instdir}/lib/ffi/platform/
|
||||||
|
%endif
|
||||||
|
cp -a .%{gem_dir}/* \
|
||||||
|
%{buildroot}%{gem_dir}/
|
||||||
|
mkdir -p %{buildroot}%{gem_extdir_mri}
|
||||||
|
cp -a .%{gem_extdir_mri}/{gem.build_complete,*.so} %{buildroot}%{gem_extdir_mri}/
|
||||||
|
rm -rf %{buildroot}%{gem_instdir}/ext/
|
||||||
|
|
||||||
|
%check
|
||||||
|
pushd .%{gem_instdir}
|
||||||
|
ln -s %{_builddir}/%{gem_name}-%{version}/spec spec
|
||||||
|
pushd spec/ffi/fixtures
|
||||||
|
make JFLAGS="%{optflags}"
|
||||||
|
popd
|
||||||
|
rspec -I$(dirs +1)%{gem_extdir_mri} spec
|
||||||
|
popd
|
||||||
|
|
||||||
|
%files
|
||||||
|
%dir %{gem_instdir}
|
||||||
|
%{gem_extdir_mri}
|
||||||
|
%exclude %{gem_instdir}/.*
|
||||||
|
%license %{gem_instdir}/COPYING
|
||||||
|
%license %{gem_instdir}/LICENSE
|
||||||
|
%license %{gem_instdir}/LICENSE.SPECS
|
||||||
|
%exclude %{gem_instdir}/appveyor.yml
|
||||||
|
%{gem_libdir}
|
||||||
|
%exclude %{gem_cache}
|
||||||
|
%{gem_spec}
|
||||||
|
|
||||||
|
%files doc
|
||||||
|
%doc %{gem_docdir}
|
||||||
|
%doc %{gem_instdir}/CHANGELOG.md
|
||||||
|
%{gem_instdir}/Gemfile
|
||||||
|
%doc %{gem_instdir}/README.md
|
||||||
|
%{gem_instdir}/Rakefile
|
||||||
|
%{gem_instdir}/samples
|
||||||
|
%{gem_instdir}/ffi.gemspec
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Mon Jul 10 2023 laokz <zhangkai@iscas.ac.cn> - 1.10.0-5
|
||||||
|
- backport upstream patch to support riscv64
|
||||||
|
|
||||||
|
* Thu May 18 2023 Wenlong Zhang <zhangwenlong@loongson.cn> - 1.10.0-4
|
||||||
|
- add loongarch64 support for rubygem-ffi
|
||||||
|
|
||||||
|
* Tue May 10 2022 yaoxin <yaoxin30@h-partners.com> - 1.10.0-3
|
||||||
|
- License compliance rectification
|
||||||
|
|
||||||
|
* Wed Jan 26 2022 liyanan <liyanan32@huawei.com> - 1.10.0-2
|
||||||
|
- Remove taint support
|
||||||
|
|
||||||
|
* Thu Aug 20 2020 xiezheng <xiezheng4@huawei.com> - 1.10.0-1
|
||||||
|
- package init
|
||||||
4
rubygem-ffi.yaml
Normal file
4
rubygem-ffi.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
version_control: github
|
||||||
|
src_repo: ffi/ffi
|
||||||
|
tag_prefix: ""
|
||||||
|
separator: "."
|
||||||
Loading…
x
Reference in New Issue
Block a user