Showing posts with label misc. Show all posts
Showing posts with label misc. Show all posts

Thursday, October 29, 2020

When MATLAB says "too many output arguments" after newly declaring one

I recently adjusted a MATLAB function in an existing codebase to add a new optional output argument. I was confused to see that trying to invoke it with the new argument failed with "too many output arguments." (I did save the file! And tried restarting MATLAB.) The problem was that the function was also declared in a class file, which I hadn't modified. Updating that declaration to match the implementation file fixed the problem. I imagine this also applies to "too many input arguments."

Friday, October 23, 2020

JGit's addCeilingDirectory adds an exclusive bound

A Gradle plugin I worked on uses the JGit library to check the state of the project's Git repository, if it's in one. A discrepancy in behavior between Java versions led me to investigate the FileRepositoryBuilder setup. addCeilingDirectory is supposed to set the outermost directory that will be searched by findGitDir, but due to the order in which findGitDir updates its "directory under examination" variable and checks whether the ceiling has been hit, the specified ceiling will actually not be checked. To work around this, I specified the parent directory of my intended ceiling.

Sunday, September 6, 2020

Tiny Blogger glitch: extra space

Since Google revamped the Blogger management UI to be more modern and bubbly, there's been a tiny glitch with the post editor. When starting a new post, the editor box initially contains one space, so clicking in the box and just starting to type makes the first line start shifted to the right slightly. Deleting the initial space is easy, it's just a strange UI thing.

Friday, September 4, 2020

Selecting a Python virtualenv in Visual Studio Code

I'm using Visual Studio Code to do some Python development over SSH. The project is in a virtualenv, so many packages are not available system-wide, so for autocomplete to fully work VSCode needs to recognize the virtual environment. For some reason I thought this would be more complicated than it is: when selecting the Python interpreter, pick the python symlink inside the virtualenv's bin folder. I also enabled the "Activate Env In Current Terminal" so the shell in the Terminal tab would be immediately ready to go. VSCode doesn't consistently display the environment as a virtualenv in the status bar, at least over SSH, but autocomplete picked up the libraries.

Saturday, August 15, 2020

When VMs won't keep an IPv4 address

Today while troubleshooting Internet slowness on my laptop I noticed that a virtual machine I had running lacked an IPv4 address. It had an IPv6 address and could connect to some sites including the host machine. After some stumbling around I found this Ask Ubuntu answer which mentioned clock skew. Sure enough, my modem/router's time was an hour off, possibly due to automatic Daylight Savings Time adjustment being disabled? I fixed that and made the VM reattempt DHCP configuration. It got an IP address, but with a very short lease. A little while later I found that its IP became the same as the host's, which was concerning. I only got it to hold onto a unique IP by adding a DHCP reservation in the router settings.

Friday, July 17, 2020

The Woocommerce gettext hook receives already-escaped HTML

Today I needed to change the "Billing & Shipping" label on a Woocommerce checkout page. Conveniently there is a gettext hook to which functions can be attached to postprocess the results of translation. This thread has an example, but just adjusting the target text did not work. It turns out that the first $translated_text parameter receives HTML-escaped text, so I actually needed to compare against "Billing & Shipping".

Monday, July 13, 2020

Creating tables with SQL in phpPgAdmin

I'm working on setting up a PostgreSQL database hosted on Namecheap's shared hosting, which seems to only allow access through the phpPgAdmin web app. I'm testing things in a local PostgreSQL instance with a different interface and copying the table definitions to the shared server as SQL "create" commands when ready. I first tried pasting it into the box on the "SQL" tab of the database object, but phpPgAdmin seems to wrap the command in a way that makes it invalid. However, there is a small "SQL" link in the far upper right of the page that produces a new window. Arbitrary commands can be successfully run from there.

Thursday, July 9, 2020

PostgreSQL users may need to be added to databases manually on Namecheap

I recently set up a PostgreSQL database on Namecheap's shared hosting platform. The cPanel interface allowed me to create the database and a user for it, but even after adding the user to the database my app was denied access to the tables. It seems that cPanel didn't actually grant the new user any permissions on the database. To do that, I had to go into phpPgAdmin, go to the database, switch to the Privileges section, and use the Grant link to grant the user privileges.

Wednesday, June 3, 2020

Theming the PCKF

This past week I spent some time customizing the theme of the Keen forum. A new theme was long overdue from the migration to phpBB 3. I started by just replacing a bunch of CSS colors to a green-and-yellow theme like the previous forum, which helped a lot by itself. Community members suggested other adjustments including a header background image from the game. That took some fiddling to get right but looks really good!

Sunday, May 24, 2020

Gradle scripts for publishing to Maven Central shouldn't sign specific files

About a year ago, I deployed a Gradle project to Maven Central, which was made difficult by the signing requirement. I found a third-party guide that provided a very long snippet of buildscript to explicitly sign the POM (project manifest XML file) and various other files. After updating the project to Gradle 6, that didn't work anymore; the files that got signed were not the ones actually uploaded, so the signatures were invalid. Gradle 6 also introduced a new file that wasn't getting signed properly. After some poking around I discovered that signing specific files is not necessary when using the maven-publish plugin. The signing plugin can sign an entire publication as long as its configuration is written after the part of the buildscript that declares the publication:

signing {
    sign publishing.publications.getByName("mavenJava")
}

That change also made my check for duplicate signed files unnecessary.

A full working version can be found on GitHub.

Monday, April 27, 2020

Nested Git repositories can appear as phantom submodules

Tonight I helped a student who was trying to publish a project to GitHub with Android Studio but only got one subfolder in the resulting GitHub repository. git status showed that the published subfolder was a submodule with pending changes. Strangely, there was no .gitmodules file for submodule registration. There was, however, another .git directory inside that folder - it was actually a nested repository. To fix that accident, we:

  1. Deleted the subfolder's .git directory
  2. Removed the submodule from the outer repository's Git index with git rm --cached theFolder
  3. Committed the change
  4. Added the subfolder back, now as a plain directory, with git add theFolder
  5. Committed the change

Saturday, April 4, 2020

JavaCompiler Diagnostic objects might not include a source

Today I was working with a project that uses the JavaCompiler API for in-memory compilation of Java sources. It accesses the compiler's Diagnostics to report compilation errors. It assumed that getSource would return a source file for each diagnostic, but that is not the case and it choked on a warning about a lack of annotation processor for a certain annotation. Initially I just wrote an inert annotation processor to squelch the warning, but then I went through the project that was the direct cause and fixed it to not assume a specific source for each diagnostic.

Saturday, March 28, 2020

Ubuntu's default Node JS version may not be what you want

I was trying to get a Node JS application running inside Bash on Ubuntu on Windows. I successfully installed Node with the Apt package manager, but some library failed to install, citing a missing node program. Symbolic-linking that to nodejs kind of worked but produced errors about unknown (seemingly newer) syntax. After some fiddling around I learned of NVM. Installing that and the current LTS Node version was easy and made the program work as expected.

Friday, February 21, 2020

Implications of the Kotlin coroutines dispatcher initializing only once

I'm working on a project that tries to run several tasks in sandboxes in a Java process. It would be ideal to support Kotlin coroutines inside the sandboxes, but the default dispatcher causes a problem. The first time a coroutine is scheduled on the shared thread pool, the pool threads are started inside the current thread group. If that's triggered by trusted code, the threads belong to a trusted group but can be borrowed by untrusted coroutines. If the creation is triggered by untrusted code, the pool threads are associated with that one job which can be torn down, ruining the pool for any other jobs.

Since the pool is a static member of some internal class, I ended up needing to reload the coroutines library into each untrusted classloader. That way, every copy of the class has its own static members that are initialized inside the sandbox and apply only to one job.

Saturday, February 8, 2020

app-ads.txt for Google Play apps

I recently got an email from Google AdMob urging me to add an app-ads.txt file for one of my Google Play apps. This email directed me to a PDF of a technical specification which referred to another prior specification. While I could have spent the time digging into the details, it seemed strange to me that Google would say "here's the specs, go do the thing!" since they're usually quite developer-friendly. I looked through the specs a bit and tried researching what app-ads.txt is supposed to do and did not get far in the brief time I investigated.

But reading on in the email and poking around, I eventually discovered that understanding all the rules and goals of the file was not necessary. The AdMob console's "how to set up app-ads.txt" button mentioned by the email contains an AdMob-user-specific snippet that can be the entire content of the file. This was not clear to me because step 1 was to create the file "using the spec provided by the IAB Tech Lab."

So I specified an URL for my app in its Google Play listing, created app-ads.txt in its root as directed, and pasted the snippet into it. (I also went ahead and added a CONTACT line.) The next day, the AdMob console confirmed that the file was set up properly.

Friday, January 31, 2020

Gson can create Kotlin objects with surprisingly null parameters

One of my projects uses Gson to load a bit of state from a JSON file. The state is represented by a Kotlin data class with non-null properties. I expected that instances of this class would fail to initialize if Gson didn't find a JSON property for all the properties, in which case the program would fall back to my default. Instead it created an instance with that non-null-declared property set to null, which produced a confusing stack trace. Checking the property against null works, of course, but Kotlin produces a "senseless comparison" warning.

Saturday, January 25, 2020

IntelliJ "apply patch" doesn't use Git

The class I'm on staff for historically distributed updates to its assignment as patches generated by git diff. Students would apply them to their projects with the VCS | Apply Patch feature of IntelliJ (Android Studio, in our case). This appeared to work pretty well, but eventually I noticed a case where not all changes from the patch were actually applied to the project. Apparently the "apply patch" feature is not powered by Git, even in Git diffs for Git projects. Using git apply from the Terminal tab works better.

Wednesday, January 15, 2020

Directories may or may not have their own entries in ZIPs

Today I found that one of my Gradle plugins choked on a JAR file that should have been perfectly normal. My plugin tried to extract the JAR by creating a file on disk for each entry, which ended up including directories. That was surely a bug, but it was strange that only some JAR files triggered it. Specifically, JARs created by a Gradle Java project jar task caused the problem, but those created by an Android createFullJarVariant task did not.

Apparently it is optional for ZIP (JAR) "entries" to be created for directories, even if there are files in those subdirectories. I examined example JARs in PowerShell with the ZipArchive class, finding that only the crash-causing JAR had directories in its Entries collection.

Wednesday, January 8, 2020

Building Gradle plugins with Maven

Today I started writing a Gradle plugin module for a project that uses Maven as its build system. I know it's possible, with some fiddling, to involve a Gradle build in a Maven setup, but this project is managed by someone else and I wanted to stay with their preferred technology as much as possible.

Since Gradle plugins are ultimately just JARs, it's possible to compile them with Maven. Of course, this loses Gradle's convenient facilitation of writing Gradle plugins. Specifically, you need to add various dependencies yourself rather than just using gradleApi(). These <dependency>s generally look like:

<groupId>org.gradle</groupId>
<artifactId>gradle-something</artifactId>
<version>5.6.4</version>
<scope>provided</scope>

I'm currently using version 5.6.4 because it's the latest version of the Gradle 5 series, which supported by Android Studio and used by a lot of projects. The "provided" scope makes it used only for compilation, never bundled with the plugin. You may also need a reference to Groovy.

The various types are spread across quite a few artifacts. For a pretty straightforward plugin (doing some extra stuff with the results of Java compilation), I needed dependencies on gradle-core, gradle-core-api, gradle-base-services, gradle-model-core, gradle-language-jvm, gradle-language-java, gradle-platform-jvm, gradle-plugins, and gradle-tooling-api. To determine which artifact provides a class the compiler can't find, you can search the Gradle monorepository.

For adding the plugin metadata, the properties file can go in the same place under resources/META-INF that it would with a Gradle build.

Monday, September 30, 2019

Android Chrome may not redirect to custom URI schemes automatically

Single Sign-On authentication for the Moodle mobile app works by opening the SSO page in a browser window and trusting the browser to redirect after the login to a custom URI scheme handled by the app. Interestingly, this works when the user was already logged into Moodle in their browser, but not after completing the SSO flow. Apparently the Chrome browser sometimes won't honor an HTTP Location redirect to a custom URI scheme. In Moodle's case, the confirmed=true query parameter can be added to make the page display some nice UI with a link to proceed to the app.