Skip to content

Commit 72bf656

Browse files
authored
Merge branch 'main' into upgrade_catch2_to_3.7.0
2 parents 49d004a + 1574a67 commit 72bf656

File tree

12 files changed

+236
-60
lines changed

12 files changed

+236
-60
lines changed

.github/workflows/release.yml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Copyright (c) 2021 Concurrent Technologies Corporation.
2-
#
2+
#
33
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
4-
# with the License. You may obtain a copy of the License at
5-
#
6-
# http://www.apache.org/licenses/LICENSE-2.0
7-
#
8-
# Unless required by applicable law or agreed to in writing, software is distributed under the License is
9-
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10-
# implied. See the License for the specific language governing permissions and limitations under the License.
4+
# with the License. You may obtain a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software is distributed under the License is
9+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10+
# implied. See the License for the specific language governing permissions and limitations under the License.
1111

1212
---
1313
name: Automatic Release
@@ -16,7 +16,7 @@ on:
1616
tags:
1717
- 'v*.*.*'
1818
env:
19-
node_version: 16
19+
node_version: 18
2020
export_cmd: |
2121
GIT_TAG=$(echo ${GITHUB_REF#refs/*/} | cut -d 'v' -f 2)
2222
PKG_VERSION=$(echo $(node -p "JSON.stringify(require('./package.json').version)") | sed 's|"||g')
@@ -42,7 +42,7 @@ jobs:
4242
# This check name is defined as the github action job name (in .github/workflows/testing.yaml)
4343
checkName: "Rat Check 🐀"
4444
ref: ${{ github.event.pull_request.head.sha || github.sha }}
45-
45+
4646
- name: Check Scala format ✅
4747
uses: fountainhead/[email protected]
4848
id: scala-format
@@ -51,7 +51,7 @@ jobs:
5151
# This check name is defined as the github action job name (in .github/workflows/testing.yaml)
5252
checkName: "Scala Code Format"
5353
ref: ${{ github.event.pull_request.head.sha || github.sha }}
54-
54+
5555
- name: Check TypeScript format ✅
5656
uses: fountainhead/[email protected]
5757
id: ts-format
@@ -60,7 +60,7 @@ jobs:
6060
# This check name is defined as the github action job name (in .github/workflows/testing.yaml)
6161
checkName: "TypeScript code is properly formatted"
6262
ref: ${{ github.event.pull_request.head.sha || github.sha }}
63-
63+
6464
- name: Check tests - macOS 12 ✅
6565
uses: fountainhead/[email protected]
6666
id: macos12-tests
@@ -69,7 +69,7 @@ jobs:
6969
# This check name is defined as the github action job name (in .github/workflows/testing.yaml)
7070
checkName: "Build middleware macos-12 🔧"
7171
ref: ${{ github.event.pull_request.head.sha || github.sha }}
72-
72+
7373
- name: Check tests - macOS 14 ✅
7474
uses: fountainhead/[email protected]
7575
id: macos14-tests
@@ -96,7 +96,7 @@ jobs:
9696
# This check name is defined as the github action job name (in .github/workflows/testing.yaml)
9797
checkName: "Build middleware windows-2019 🔧"
9898
ref: ${{ github.event.pull_request.head.sha || github.sha }}
99-
99+
100100
- name: Check native build arm64 - Linux ✅
101101
uses: fountainhead/[email protected]
102102
id: ubuntu-arm64-native
@@ -178,7 +178,7 @@ jobs:
178178
- name: Export git tag and package.json version 🚢
179179
run: ${{ env.export_cmd }}
180180
shell: bash
181-
181+
182182
- name: Download upload_url 🔻
183183
uses: actions/download-artifact@v4
184184
with:
@@ -195,7 +195,7 @@ jobs:
195195
distribution: temurin
196196
java-version: 8
197197
cache: sbt
198-
198+
199199
- name: Make _install directory to store lib files
200200
run: mkdir -p _install
201201

@@ -207,7 +207,7 @@ jobs:
207207
workflow_conclusion: success
208208
name: ubuntu-20.04-x64-libomega_edit.so
209209
path: _install/libomega_edit_linux_amd64.so
210-
210+
211211
- name: Download linux arm64 library file 🔻
212212
uses: dawidd6/action-download-artifact@v3
213213
with:
@@ -216,7 +216,7 @@ jobs:
216216
workflow_conclusion: success
217217
name: ubuntu-20.04-arm64-libomega_edit.so
218218
path: _install/libomega_edit_linux_aarch64.so
219-
219+
220220
- name: Download macos-12 library file 🔻
221221
uses: dawidd6/action-download-artifact@v3
222222
with:
@@ -234,7 +234,7 @@ jobs:
234234
workflow_conclusion: success
235235
name: macos-12-x64-libomega_edit.dylib
236236
path: _install/libomega_edit_macos_x86_64.dylib
237-
237+
238238
- name: Download windows library file 🔻
239239
uses: dawidd6/action-download-artifact@v3
240240
with:

.github/workflows/ts-format.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ jobs:
2929
with:
3030
fetch-depth: 0
3131
persist-credentials: false
32-
32+
3333
- name: Setup Node 📐
3434
uses: actions/setup-node@v4
3535
with:
3636
registry-url: 'https://registry.npmjs.org'
37-
node-version: 16
37+
node-version: 18
3838

3939
- name: yarn lint - all workspaces 🧶
4040
run: |

packages/client/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@
4343
"ts-node": "^10.9.2"
4444
},
4545
"dependencies": {
46-
"@grpc/grpc-js": "1.10.9",
46+
"@grpc/grpc-js": "1.12.2",
4747
"@omega-edit/server": "0.9.82",
4848
"@types/google-protobuf": "3.15.12",
49-
"google-protobuf": "3.21.2",
50-
"pid-port": "0.2.0",
51-
"pino": "8.20.0",
49+
"google-protobuf": "3.21.4",
50+
"pid-port": "1.0.0",
51+
"pino": "9.5.0",
5252
"wait-port": "1.1.0"
5353
}
5454
}

packages/client/src/server.ts

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ import {
3333
ServerControlResponse,
3434
ServerInfoResponse,
3535
} from './omega_edit_pb'
36+
import { execFile } from 'child_process'
37+
import { promisify } from 'util'
38+
39+
// Convert execFile to a promise-based function
40+
const execFilePromise = promisify(execFile)
3641

3742
const DEFAULT_PORT = 9000 // default port for the server
3843
const DEFAULT_HOST = '127.0.0.1' // default host for the server
@@ -233,6 +238,36 @@ export async function stopProcessUsingPID(
233238
return true
234239
}
235240

241+
/**
242+
* Get the process id using the port
243+
* @param port port to check
244+
* @returns process id or undefined if the port is not in use
245+
*/
246+
async function getPidByPort(port: number): Promise<number | undefined> {
247+
try {
248+
// Try to get the PID using `lsof`
249+
const { stdout } = await execFilePromise('lsof', [
250+
'-iTCP:' + port,
251+
'-sTCP:LISTEN',
252+
'-n',
253+
'-P',
254+
])
255+
const lines = stdout.trim().split('\n')
256+
if (lines.length > 1) {
257+
const [_, pid] = lines[1].trim().split(/\s+/)
258+
return parseInt(pid, 10)
259+
}
260+
return undefined
261+
} catch (error) {
262+
// Fallback to `portToPid` if `lsof` fails
263+
try {
264+
return await portToPid(port)
265+
} catch (portToPidError) {
266+
return undefined
267+
}
268+
}
269+
}
270+
236271
/**
237272
* Stop the service running on a port
238273
* @param port port
@@ -250,21 +285,42 @@ export async function stopServiceOnPort(
250285
signal,
251286
}
252287
log.debug(logMetadata)
288+
253289
try {
254-
const pid = await portToPid(port)
255-
return pid ? stopProcessUsingPID(pid as number, signal) : true
290+
// Attempt to get the PID for the given port
291+
const pid = await getPidByPort(port)
292+
293+
if (pid) {
294+
log.debug({ ...logMetadata, msg: `Found PID ${pid} for port ${port}` })
295+
296+
// Attempt to stop the process using the PID
297+
const result = await stopProcessUsingPID(pid, signal)
298+
log.debug({
299+
...logMetadata,
300+
msg: `stopProcessUsingPID result: ${result}`,
301+
})
302+
return result
303+
} else {
304+
log.debug({
305+
...logMetadata,
306+
stopped: true,
307+
msg: 'No process found using the port',
308+
})
309+
return true // No process was using the port, so consider it as stopped
310+
}
256311
} catch (err) {
312+
// Handle case where `portToPid` cannot find a process for the port
257313
if (err instanceof Error) {
258314
if (err.message.startsWith('Could not find a process that uses port')) {
259315
log.debug({
260316
...logMetadata,
261317
stopped: true,
262318
msg: err.message,
263319
})
264-
// if the port is not in use, return true
265-
return true
320+
return true // No process using the port, so we consider it stopped
266321
}
267-
log.debug({
322+
// Log other types of errors that occur
323+
log.error({
268324
...logMetadata,
269325
stopped: false,
270326
err: {
@@ -279,8 +335,8 @@ export async function stopServiceOnPort(
279335
err: { msg: String(err) },
280336
})
281337
}
338+
return false // Return false for any errors that occur
282339
}
283-
return false
284340
}
285341

286342
/**
@@ -563,7 +619,10 @@ export function pidIsRunning(pid) {
563619
process.kill(pid, 0)
564620
return true
565621
} catch (e) {
566-
return false
622+
if ((e as NodeJS.ErrnoException).code === 'ESRCH') {
623+
return false
624+
}
625+
throw e
567626
}
568627
}
569628

packages/client/tests/specs/common.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,13 @@ export async function subscribeViewport(
171171
: 1
172172
)
173173
const event = viewportEvent.getViewportEventKind()
174+
const viewport_id_from_event = viewportEvent.getViewportId()
174175
if (ViewportEventKind.VIEWPORT_EVT_EDIT == event) {
175176
log_info(
176177
'viewport_id: ' +
177178
viewport_id +
179+
', viewport_id_from_event: ' +
180+
viewport_id_from_event +
178181
', event: ' +
179182
event +
180183
', serial: ' +
@@ -188,6 +191,15 @@ export async function subscribeViewport(
188191
'", callbacks: ' +
189192
viewport_callbacks.get(viewport_id)
190193
)
194+
if (viewport_id_from_event !== viewport_id) {
195+
log_error(
196+
'viewport ID mismatch: "' +
197+
viewport_id +
198+
'" not equal to "' +
199+
viewport_id_from_event +
200+
'"'
201+
)
202+
}
191203
} else {
192204
log_info(
193205
'viewport: ' +

packages/client/tests/specs/viewport.spec.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,15 @@ describe('Viewports', () => {
176176
await checkCallbackCount(viewport_callbacks, viewport_1_id, 1)
177177
await checkCallbackCount(viewport_callbacks, viewport_2_id, 3)
178178
log_info(viewport_callbacks)
179+
179180
// Unsubscribe all viewporta
180-
await unsubscribeViewport(viewport_1_id)
181-
await unsubscribeViewport(viewport_2_id)
181+
expect(await unsubscribeViewport(viewport_1_id)).to.equal(viewport_1_id)
182+
expect(await unsubscribeViewport(viewport_2_id)).to.equal(viewport_2_id)
183+
182184
// Note the viewports are not destroyed, just unsubscribed
183185
expect(await getViewportCount(session_id)).to.equal(1)
184-
await destroyViewport(viewport_1_id)
186+
187+
expect(await destroyViewport(viewport_1_id)).to.equal(viewport_1_id)
185188
expect(await getViewportCount(session_id)).to.equal(0)
186189
}).timeout(8000)
187190

@@ -304,6 +307,7 @@ describe('Viewports', () => {
304307
false
305308
)
306309
const viewport_id = viewport_response.getViewportId()
310+
expect(viewport_id).to.equal(session_id + ':' + desired_viewport_id)
307311
expect(await viewportHasChanges(viewport_id)).to.be.false
308312
expect(viewport_response.getData_asU8()).to.deep.equal(Buffer.from(''))
309313
expect(viewport_response.getLength()).to.equal(0)
@@ -414,7 +418,9 @@ describe('Viewports', () => {
414418
)
415419
expect(await getViewportCount(session_id)).to.equal(1)
416420
// Unsubscribe the viewport
417-
expect(await unsubscribeViewport(viewport_id)).to.equal(desired_viewport_id)
421+
expect(await unsubscribeViewport(viewport_id)).to.equal(
422+
session_id + ':' + desired_viewport_id
423+
)
418424
// Note the viewport is not destroyed, just unsubscribed
419425
expect(await getViewportCount(session_id)).to.equal(1)
420426
await destroyViewport(viewport_id)

packages/server/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ async function executeServer(args: string[]): Promise<ChildProcess> {
9191
stdio: ['ignore', 'ignore', 'ignore'],
9292
detached: true,
9393
windowsHide: true, // avoid showing a console window
94+
shell: os.platform().startsWith('win'), // use shell on Windows because it can't execute scripts directly
9495
})
9596

9697
serverProcess.on('error', (err: Error) => {

server/scala/api/src/main/scala/com/ctc/omega_edit/ViewportImpl.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ private[omega_edit] class ViewportImpl(p: Pointer, i: FFI) extends Viewport {
6767

6868
def modify(offset: Long, capacity: Long, isFloating: Boolean): Boolean =
6969
i.omega_viewport_modify(p, offset, capacity, if (isFloating) 1 else 0) == 0
70+
7071
override def toString: String =
7172
data.mkString // TODO: probably render instead as hex
7273

server/scala/serv/src/main/scala/com/ctc/omega_edit/grpc/EditorService.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ class EditorService(implicit val system: ActorSystem) extends Editor {
444444
ObjectId(in.id) match {
445445
case Viewport.Id(sid, vid) =>
446446
(editors ? ViewportOp(sid, vid, Viewport.Unwatch)).mapTo[Result].map {
447-
case Ok(id) => ObjectId(id)
447+
case Ok(_) => in
448448
case Err(c) => throw grpcFailure(c)
449449
}
450450
case _ =>

server/scala/serv/src/main/scala/com/ctc/omega_edit/grpc/Session.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ class Session(
194194
val vid = id.getOrElse(Viewport.Id.uuid())
195195
val fqid = s"$sessionId:$vid"
196196

197-
context.child(fqid) match {
197+
context.child(vid) match {
198198
case Some(_) =>
199199
sender() ! Err(Status.ALREADY_EXISTS)
200200
case None =>
@@ -204,8 +204,8 @@ class Session(
204204
val cb = ViewportCallback { (v, e, c) =>
205205
input.queue.offer(
206206
ViewportEvent(
207-
sessionId = fqid,
208-
viewportId = vid,
207+
sessionId = sessionId,
208+
viewportId = fqid,
209209
serial = c.map(_.id),
210210
data = Option(ByteString.copyFrom(v.data)),
211211
length = Some(v.data.size.toLong),

0 commit comments

Comments
 (0)